<template>
	<div ref="forPrint" class="table-container">
		<div v-if="props.config?.isSub === true && props.config?.isDisabled !== true" style="text-align: right; margin-bottom: 12px">
			<el-button type="success" class="ml10" @click="subCreate()">
				<i class="fa fa-plus"></i>
				{{ $t('message._system.common.vm.add') }}
			</el-button>
		</div>
		<!-- 批量编辑操作按钮 -->
		<div v-if="hasEditableColumns && state.editingRows.size > 0" class="batch-edit-toolbar">
			<div class="batch-edit-info">
				<i class="fa fa-edit"></i>
				<span
					>正在编辑 <strong>{{ state.editingRows.size }}</strong> 条记录</span
				>
			</div>
			<div class="batch-edit-actions">
				<el-button type="primary" class="batch-save-btn" @click="batchSaveAll()">
					<i class="fa fa-check"></i>
					批量保存
				</el-button>
				<el-button class="batch-cancel-btn" @click="cancelAllEdit()">
					<i class="fa fa-times"></i>
					取消全部
				</el-button>
			</div>
		</div>
		<el-table
			:key="tableKey"
			ref="elTableRef"
			:default-expand-all="false"
			:data="props.config?.isSub === true ? listvalue : state.data"
			:border="setBorder"
			:size="tableSize"
			v-bind="$attrs"
			row-key="ID"
			:stripe="localConfig.isStripe !== false"
			style="width: 100%; margin-top: 12px"
			v-loading="localConfig.loading && props.config?.isSub !== true"
			@selection-change="onSelectionChange"
			@sort-change="onSortChange"
			@header-dragend="onColumnResize"
			:show-summary="localConfig.showSummary"
			:summary-method="getSummaryMethod"
			:span-method="props.spanMethod || spanMethod"
			:row-class-name="getRowClassName"
			:class="{
				'table-fixed-operation': isMoreColumns && !props.config?.isSub,
				'table-compact': tableSize === 'small',
				'table-comfortable': tableSize === 'large',
			}"
		>
			<el-table-column
				type="selection"
				:reserve-selection="true"
				width="40"
				v-if="localConfig.isSelection"
				align="center"
				:fixed="localConfig.selectionFixed || false"
			/>
			<el-table-column type="index" :label="$t('message._system.table.no')" width="50" v-if="localConfig.isSerialNo" align="center" />
			<el-table-column
				v-for="(item, index) in setHeader"
				:key="item.key"
				:show-overflow-tooltip="!['combobox', 'switch', 'date', 'textbox'].includes(item.type || 'text')"
				:prop="item.key"
				:width="getColumnWidth(item)"
				:min-width="getColumnMinWidth(item)"
				:label="getDisplayTitle(item.title)"
				:sortable="item.sortable"
				:align="item.align || 'center'"
				:resizable="true"
				:fixed="item.fixed || false"
			>
				<template #header>
					<el-tooltip v-if="isMoreColumns && item.title && item.title.length > 6" :content="item.title" placement="top">
						<span>{{ getDisplayTitle(item.title) }}</span>
					</el-tooltip>
					<span v-else>{{ getDisplayTitle(item.title) }}</span>
				</template>
				<template v-slot="scope">
					<!-- 自定义格式化器 - 但排除标签类型 -->
					<template v-if="item.formatter && item.type !== 'tag'">
						<span v-html="item.formatter(scope.row, scope.row[item.key])"></span>
					</template>
					<!-- 图片类型 -->
					<template v-else-if="item.type === 'image'">
						<div class="table-image-container">
							<el-image
								:preview-teleported="true"
								v-if="scope.row[item.key + '__localurl__'] !== ''"
								class="table-image"
								:style="getImageStyle(item)"
								:src="scope.row[item.key + '__localurl__']"
								:initial-index="scope.row[item.key + '__preview__']"
								:preview-src-list="state.picList"
								:title="$t('message._system.table.preview')"
								fit="cover"
								:hide-on-click-modal="true"
							>
								<template #placeholder>
									<div
										class="image-placeholder"
										style="background: #f0f0f0; display: flex; flex-direction: column; align-items: center; justify-content: center"
									>
										<i class="el-icon-loading" style="font-size: 20px; animation: rotate 2s linear infinite"></i>
										<span style="font-size: 10px; margin-top: 4px">加载中...</span>
									</div>
								</template>
								<template #error>
									<div class="image-error">
										<i class="el-icon-picture-outline"></i>
										<span>{{ $t('message._system.common.loadFailed') }}</span>
									</div>
								</template>
							</el-image>
						</div>
					</template>
					<!-- Base64图片类型 -->
					<template v-else-if="item.type === 'base64-image'">
						<div class="table-image-container">
							<el-image
								:preview-teleported="true"
								v-if="scope.row[item.key]"
								class="table-image"
								:style="getImageStyle(item)"
								:src="scope.row[item.key]"
								:preview-src-list="[scope.row[item.key]]"
								:title="$t('message._system.table.preview')"
								fit="cover"
								:hide-on-click-modal="true"
							>
								<template #placeholder>
									<div
										class="image-placeholder"
										style="background: #f0f0f0; display: flex; flex-direction: column; align-items: center; justify-content: center"
									>
										<i class="el-icon-loading" style="font-size: 20px; animation: rotate 2s linear infinite"></i>
										<span style="font-size: 10px; margin-top: 4px">加载中...</span>
									</div>
								</template>
								<template #error>
									<div class="image-error">
										<i class="el-icon-picture-outline"></i>
										<span>{{ $t('message._system.common.loadFailed') }}</span>
									</div>
								</template>
							</el-image>
						</div>
					</template>
					<!-- 图片列表类型 -->
					<template v-else-if="item.type === 'imageList'">
						<div v-if="scope.row[item.key] && Array.isArray(scope.row[item.key]) && scope.row[item.key].length > 0" class="table-image-container">
							<div class="image-list-wrapper">
								<!-- 显示的图片 -->
								<template
									v-for="(imageItem, index) in getDisplayImages(scope.row[item.key], item.imageListCount || 2)"
									:key="`${scope.row.ID}-${item.key}-${index}`"
								>
									<el-image
										:preview-teleported="true"
										v-if="
											scope.row[item.key + '__localurl__'] &&
											scope.row[item.key + '__localurl__'][index] &&
											scope.row[item.key + '__localurl__'][index] !== ''
										"
										class="table-image"
										:style="{
											width: item.imageWidth ? item.imageWidth + 'px' : '80px',
											height: item.imageHeight ? item.imageHeight + 'px' : '60px',
											cursor: 'pointer',
										}"
										:src="scope.row[item.key + '__localurl__'][index]"
										:initial-index="getImageListPreviewIndex(scope.row, item.key, index)"
										:preview-src-list="state.picList"
										:title="$t('message._system.table.preview')"
										fit="cover"
										:hide-on-click-modal="true"
									>
										<template #placeholder>
											<div
												class="image-placeholder"
												style="background: #f0f0f0; display: flex; flex-direction: column; align-items: center; justify-content: center"
											>
												<i class="el-icon-loading" style="font-size: 20px; animation: rotate 2s linear infinite"></i>
												<span style="font-size: 10px; margin-top: 4px">加载中...</span>
											</div>
										</template>
										<template #error>
											<div class="image-error">
												<i class="el-icon-picture-outline"></i>
												<span>{{ $t('message._system.common.loadFailed') }}</span>
											</div>
										</template>
									</el-image>
								</template>
								<!-- 更多图片提示 -->
								<div
									v-if="scope.row[item.key].length > (item.imageListCount || 2)"
									class="more-images-indicator"
									:style="getImageStyle(item)"
									@click="previewAllImages(scope.row[item.key], item.imageListCount || 2)"
								>
									<span>+{{ scope.row[item.key].length - (item.imageListCount || 2) }}</span>
								</div>
							</div>
						</div>
					</template>
					<!-- 文件预览类型（支持图片和PDF混合预览） -->
					<template v-else-if="item.type === 'filePreview'">
						<div
							v-if="scope.row[item.key] && Array.isArray(scope.row[item.key]) && scope.row[item.key].length > 0"
							class="table-file-preview-container"
						>
							<div class="file-preview-wrapper">
								<!-- 显示的文件预览 -->
								<template
									v-for="(fileItem, index) in getDisplayFiles(scope.row[item.key], item.filePreviewCount || 2)"
									:key="`${scope.row.ID}-${item.key}-${index}`"
								>
									<!-- 图片文件预览 -->
									<el-image
										v-if="isImageFile(fileItem) && scope.row[item.key + '__localurl__'] && scope.row[item.key + '__localurl__'][index]"
										:preview-teleported="true"
										class="table-file-preview table-file-preview-image"
										:style="getFilePreviewStyle(item)"
										:src="scope.row[item.key + '__localurl__'][index]"
										:initial-index="getFilePreviewIndex(scope.row, item.key, index)"
										:preview-src-list="state.previewList"
										:title="$t('message._system.table.preview')"
										fit="cover"
										:hide-on-click-modal="true"
									>
										<template #placeholder>
											<div
												class="file-placeholder"
												style="background: #f0f0f0; display: flex; flex-direction: column; align-items: center; justify-content: center"
											>
												<i class="el-icon-loading" style="font-size: 20px; animation: rotate 2s linear infinite"></i>
												<span style="font-size: 10px; margin-top: 4px">加载中...</span>
											</div>
										</template>
										<template #error>
											<div class="file-error">
												<i class="el-icon-picture-outline"></i>
												<span>{{ $t('message._system.common.loadFailed') }}</span>
											</div>
										</template>
									</el-image>
									<!-- PDF文件预览 -->
									<div
										v-else-if="isPdfFile(fileItem)"
										class="table-file-preview table-file-preview-pdf"
										:style="getFilePreviewStyle(item)"
										@click="openFilePreview(scope.row[item.key], index)"
									>
										<div class="pdf-preview-icon">
											<i class="fa fa-file-pdf-o" style="font-size: 24px; color: #f56c6c"></i>
											<span style="font-size: 10px; margin-top: 4px">PDF预览</span>
										</div>
									</div>
									<!-- 其他文件类型 -->
									<div
										v-else
										class="table-file-preview table-file-preview-other"
										:style="getFilePreviewStyle(item)"
										@click="openFilePreview(scope.row[item.key], index)"
									>
										<div class="other-file-icon">
											<i class="fa fa-file-o" style="font-size: 24px; color: #909399"></i>
											<span style="font-size: 10px; margin-top: 4px">文件预览</span>
										</div>
									</div>
								</template>
								<!-- 更多文件提示 -->
								<div
									v-if="scope.row[item.key].length > (item.filePreviewCount || 2)"
									class="more-files-indicator"
									:style="getFilePreviewStyle(item)"
									@click="openFilePreview(scope.row[item.key], item.filePreviewCount || 2)"
								>
									<span>+{{ scope.row[item.key].length - (item.filePreviewCount || 2) }}</span>
								</div>
							</div>
						</div>
					</template>
					<!-- 文件下载 -->
					<template v-else-if="item.type === 'file' && props.config?.isSub !== true">
						<el-button v-if="scope.row[item.key]" text type="primary" @click="download(scope.row[item.key])">
							{{ $t('message._system.common.vm.download') }}
						</el-button>
					</template>
					<!-- 图标 -->
					<template v-else-if="item.type === 'icon' && props.config?.isSub !== true">
						<i :class="scope.row[item.key]" style="font-size: 20px"></i>
					</template>
					<!-- 开关 - 只读模式 -->
					<template v-else-if="item.type === 'switch' && props.config?.isSub !== true">
						<el-switch :model-value="convertToBoolean(scope.row[item.key])" disabled />
					</template>
					<!-- 开关 - 编辑模式 -->
					<template v-else-if="item.type === 'switch' && props.config?.isSub === true">
						<el-switch
							v-model="listvalue[scope.$index][item.key]"
							:disabled="item.isDisabled || props.config?.isDisabled"
							@change="onSwitchChange(scope.$index, item.key, $event)"
						/>
					</template>
					<!-- 文本框 -->
					<template v-else-if="item.type === 'textbox'">
						<el-input
							v-model="listvalue[scope.$index][item.key]"
							:disabled="item.isDisabled || props.config?.isDisabled"
							:placeholder="item.placeholder"
							:maxlength="item.maxlength"
							@change="onInputChange(scope.$index, item.key, $event)"
						/>
					</template>
					<!-- 下拉框 -->
					<template v-else-if="item.type === 'combobox'">
						<el-select
							v-model="listvalue[scope.$index][item.key]"
							:disabled="item.isDisabled || props.config?.isDisabled"
							:placeholder="item.placeholder || $t('message._system.common.pleaseSelect')"
							:clearable="item.clearable !== false"
							@change="onSelectChange(scope.$index, item.key, $event)"
						>
							<el-option v-for="(op, opkey, opindex) in state.comboData[item.key]" :key="opindex" :value="getComboValue(opkey)" :label="op" />
						</el-select>
					</template>
					<!-- 日期选择器 -->
					<template v-else-if="item.type === 'date'">
						<el-date-picker
							v-if="item.dateType !== 'time'"
							v-model="listvalue[scope.$index][item.key]"
							:type="item.dateType ?? 'datetime'"
							:disabled="item.isDisabled || props.config?.isDisabled"
							:placeholder="item.placeholder"
							@change="onDateChange(scope.$index, item.key, $event)"
						/>
						<el-time-picker
							v-else
							v-model="listvalue[scope.$index][item.key]"
							:disabled="item.isDisabled || props.config?.isDisabled"
							:placeholder="item.placeholder"
							@change="onTimeChange(scope.$index, item.key, $event)"
						/>
					</template>
					<!-- 标签 -->
					<template v-else-if="item.type === 'tag'">
						<el-tag
							:type="
								getTagType(
									item.formatter ? item.formatter(scope.row, scope.row[item.key]) : scope.row[item.key],
									item,
									scope.row,
									scope.row[item.key]
								)
							"
							:size="item.tagSize || 'small'"
							:effect="item.tagEffect || 'light'"
							:color="getTagColor(scope.row[item.key], item, scope.row)"
							:round="item.tagRound === true"
						>
							{{ item.formatter ? item.formatter(scope.row, scope.row[item.key]) : formatDisplayValue(scope.row[item.key], item) }}
						</el-tag>
					</template>
					<!-- 默认文本显示 -->
					<template v-else>
						<!-- 如果是可编辑列且当前行处于编辑状态 -->
						<template v-if="item.editable && state.editingRows.has(scope.$index)">
							<!-- 根据列类型显示不同的编辑控件 -->
							<el-input
								v-if="!item.editType || item.editType === 'textbox'"
								v-model="(props.config?.isSub === true ? listvalue : state.data)[scope.$index][item.key]"
								:placeholder="item.placeholder"
								:maxlength="item.maxlength"
								size="small"
								@change="onInputChange(scope.$index, item.key, $event)"
							/>
							<el-select
								v-else-if="item.editType === 'combobox'"
								v-model="(props.config?.isSub === true ? listvalue : state.data)[scope.$index][item.key]"
								:placeholder="item.placeholder || $t('message._system.common.pleaseSelect')"
								:clearable="item.clearable !== false"
								size="small"
								@change="onSelectChange(scope.$index, item.key, $event)"
							>
								<el-option v-for="(op, opkey, opindex) in state.comboData[item.key]" :key="opindex" :value="getComboValue(opkey)" :label="op" />
							</el-select>
						</template>
						<!-- 非编辑状态的正常显示 -->
						<template v-else>
							<template v-if="item.onClick || item.link === true">
								<el-link
									class="table-cell-link"
									type="primary"
									:underline="false"
									@click.stop="item.onClick && item.onClick(scope.row, scope.row[item.key], item)"
								>
									<span class="cell-link-text text-truncate">{{ formatDisplayValue(scope.row[item.key], item) }}</span>
								</el-link>
							</template>
							<template v-else>
								<div :class="{ 'editable-cell-wrapper': item.editable }" @dblclick="item.editable && startRowEdit(scope.$index)">
									<span
										:class="{ 'text-truncate': item.truncate, 'editable-cell': item.editable }"
										:title="item.editable ? '双击编辑或点击右侧编辑按钮' : ''"
									>
										{{ formatDisplayValue(scope.row[item.key], item) }}
									</span>
									<i v-if="item.editable" class="fa fa-pencil editable-icon" :title="'可编辑字段'"></i>
								</div>
							</template>
						</template>
					</template>
				</template>
			</el-table-column>

			<slot name="operation" v-if="props.config?.isOperate && props.config?.isDisabled != true">
				<el-table-column v-if="props.config?.isSub === true" :label="$t('message._system.common.vm.operate')" width="70" fixed="right">
					<template v-slot="cell">
						<el-popconfirm :title="$t('message._system.common.confirmDelete')" @confirm="subDelete(cell.$index)">
							<template #reference>
								<el-button text type="danger" size="small">
									{{ $t('message._system.common.vm.delete') }}
								</el-button>
							</template>
						</el-popconfirm>
					</template>
				</el-table-column>
				<!-- 行内编辑操作列 -->
				<el-table-column v-else-if="hasEditableColumns" :label="$t('message._system.common.vm.operate')" width="140" fixed="right">
					<template v-slot="scope">
						<!-- 编辑状态下的按钮 -->
						<template v-if="state.editingRows.has(scope.$index)">
							<el-button type="success" size="small" @click="saveRowEdit(scope.$index)" class="edit-action-btn">
								<i class="fa fa-check"></i>
								保存
							</el-button>
							<el-button type="info" size="small" @click="cancelRowEdit(scope.$index)" class="edit-action-btn">
								<i class="fa fa-times"></i>
								取消
							</el-button>
						</template>
						<!-- 非编辑状态下的按钮 -->
						<template v-else>
							<el-button type="primary" size="small" @click="startRowEdit(scope.$index)" class="edit-trigger-btn">
								<i class="fa fa-pencil"></i>
								编辑
							</el-button>
						</template>
					</template>
				</el-table-column>
			</slot>
			<slot name="customColumn"></slot>
			<template #empty>
				<el-empty v-if="props.config?.isSub !== true" :description="$t('message._system.table.noData')" />
			</template>
		</el-table>
		<div class="table-footer" v-if="props.config?.isSub !== true">
			<el-pagination
				v-if="(localConfig.total || 0) > 0 && !localConfig.hidePagination"
				v-model:current-page="state.searcher.Page"
				v-model:page-size="state.searcher.Limit"
				:pager-count="5"
				:page-sizes="pageSizes"
				:total="localConfig.total"
				layout="total, sizes, prev, pager, next, jumper"
				background
				@size-change="onHandleSizeChange"
				@current-change="onHandleCurrentChange"
				:size="tableSize"
			/>
			<div class="table-footer-tool">
				<el-popover
					v-if="localConfig.hideSetting != true"
					placement="top-end"
					trigger="click"
					transition="el-zoom-in-top"
					popper-class="table-tool-popper"
					:width="300"
					:persistent="true"
					:teleported="true"
				>
					<template #reference>
						<div class="table-tool-btn" :aria-label="$t('message._system.table.setting')">
							<i class="fa fa-gear"></i>
							<span>{{ $t('message._system.table.setting') }}</span>
						</div>
					</template>
					<template #default>
						<div class="tool-box">
							<el-tooltip :content="$t('message._system.table.drag')" placement="top-start">
								<i class="ml11 fa fa-question" :size="17" color="#909399"></i>
							</el-tooltip>
							<el-checkbox
								v-model="state.checkListAll"
								:indeterminate="state.checkListIndeterminate"
								class="ml10 mr1"
								:label="$t('message._system.table.columns')"
								@change="onCheckAllChange"
							/>
							<el-checkbox v-model="localConfig.isSerialNo" class="ml12 mr1" :label="$t('message._system.table.no')" />
							<el-checkbox v-model="localConfig.isSelection" class="ml12 mr1" :label="$t('message._system.table.multi')" />
						</div>
						<div class="tool-box" style="border-bottom: 1px solid var(--el-border-color-lighter); padding: 8px 12px">
							<el-button size="small" type="primary" @click="resetColumnWidths" style="width: 100%">
								<i class="fa fa-refresh mr-2"></i>
								重置列宽
							</el-button>
						</div>

						<div class="tool-box" style="border-bottom: 1px solid var(--el-border-color-lighter); padding: 8px 12px">
							<el-button size="small" @click="togglePermanentHide" style="width: 100%">
								<i class="fa fa-eye-slash mr-2"></i>
								{{ permanentlyHiddenCount > 0 ? '取消永久隐藏' : '永久隐藏未选列' }}
							</el-button>
							<el-button size="small" type="warning" @click="resetCurrentTableSettings" style="width: 100%">
								<i class="fa fa-undo mr-2"></i>
								重置本表设置
							</el-button>
						</div>
						<div class="tool-scroll-container" style="max-height: 240px; overflow-y: auto">
							<div ref="toolSetRef" class="tool-sortable">
								<div
									class="tool-sortable-item"
									v-for="(v, index) in localHeader"
									:key="v.key"
									:data-key="v.key"
									:draggable="true"
									@dragstart="handleDragStart($event, index)"
									@dragover="handleDragOver($event)"
									@drop="handleDrop($event, index)"
									@dragend="handleDragEnd"
								>
									<i class="fa fa-arrows-alt handle cursor-pointer" :aria-label="$t('message._system.table.dragColumn')"></i>
									<el-checkbox v-model="v.isCheck" class="ml12 mr8" :label="v.title" @change="onCheckChange" :disabled="v.isPermanentlyHidden" />
								</div>
							</div>
						</div>
					</template>
				</el-popover>
				<div v-if="localConfig.hidePrint != true" class="table-tool-btn" @click="doPrint" :aria-label="$t('message._system.table.print')">
					<i class="fa fa-print"></i>
					<span>{{ $t('message._system.table.print') }}</span>
				</div>
				<div
					v-if="localConfig.hideRefresh != true"
					class="table-tool-btn"
					@click="doSearch(null, null, isTreeState)"
					:aria-label="$t('message._system.table.refresh')"
				>
					<i class="fa fa-refresh"></i>
					<span>{{ $t('message._system.table.refresh') }}</span>
				</div>
				<el-tooltip v-if="localConfig.hideDensity != true" :content="densityTooltipText" placement="top">
					<div class="table-tool-btn table-density-toggle" @click="toggleTableDensity" :aria-label="densityTooltipText">
						<i
							class="fa"
							:class="{
								'fa-compress': tableSize === 'large',
								'fa-expand': tableSize === 'small',
								'fa-arrows-alt': tableSize === 'default',
							}"
						></i>
						<span>{{ densityText }}</span>
					</div>
				</el-tooltip>
				<div
					v-if="localConfig.showCalculateBtn"
					class="table-tool-btn"
					@click="doCalculate"
					:aria-label="'计算合计'"
					:class="{ loading: state.calculating }"
				>
					<i class="fa" :class="state.calculating ? 'fa-spinner fa-spin' : 'fa-plus-circle'"></i>
					<span>{{ state.calculating ? '计算中...' : '合计' }}</span>
				</div>
			</div>
		</div>

		<!-- 现代化文件预览组件 -->
		<FilePreview
			v-model:visible="filePreviewVisible"
			v-model:currentIndex="currentPreviewIndex"
			:files="currentPreviewFiles"
			:downloadHandler="handleFileDownload"
			:externalLoading="isLoadingPreview"
		/>
	</div>
</template>

<!--
/**
 * =====================================================================================
 * NetX 高级数据表格组件 v2.0
 * =====================================================================================
 * 
 * 【组件概述】
 * 这是一个功能丰富、高度可定制的Vue 3数据表格组件，基于Element Plus构建。
 * 支持复杂的数据展示、编辑、排序、筛选、分页等功能，适用于各种数据管理场景。
 * 
 * 【核心功能模块】
 * 1. 🔧 数据管理：支持本地数据和远程API数据，自动处理分页和排序
 * 2. 🎨 列类型支持：文本、图片、开关、下拉框、日期选择器、标签等多种类型
 * 3. ✏️ 行内编辑：支持子表格模式下的实时编辑功能
 * 4. 📷 图片处理：支持单图和多图展示，自动生成缩略图和预览
 * 5. ⚙️ 个性化设置：列显示/隐藏、列宽调整、列顺序拖拽、密度切换
 * 6. 📊 统计计算：支持前端和后端统计，可配置合计、平均值等
 * 7. 🖨️ 数据导出：支持打印和数据导出功能
 * 8. 📱 响应式设计：适配桌面端和移动端显示
 * 
 * 【使用场景】
 * - 数据管理后台的CRUD操作
 * - 复杂数据的展示和编辑
 * - 需要个性化设置的数据列表
 * - 包含图片和富媒体内容的数据表格
 * 
 * 【技术特点】
 * - TypeScript支持，完整的类型定义
 * - 响应式状态管理，数据变更实时同步
 * - 内存优化，大数据集高性能渲染
 * - 可扩展的插件架构，支持自定义列类型
 * - 无障碍访问支持，良好的用户体验
 * 
 * @author NetX Team
 * @version 2.0.0
 * @since 2024
 */
-->

<script setup lang="ts" name="netxTable">
import { reactive, computed, nextTick, ref, onMounted, watch, onUnmounted, withDefaults } from 'vue';
import { useRouter } from 'vue-router';
import fileapi from '/@/api/file';
import '/@/theme/tableTool.scss';
import { AxiosResponse } from 'axios';
import printJs from 'print-js';
import other from '/@/utils/other';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Loading, ArrowLeft, ArrowRight, Download, Close } from '@element-plus/icons-vue';
import FilePreview from '../filePreview/index.vue';

// ============ 常量定义 ============

/** 表格相关常量配置 */
const TABLE_CONSTANTS = {
	/** 默认图片尺寸配置 */
	IMAGE: {
		DEFAULT_WIDTH: 80,
		DEFAULT_HEIGHT: 60,
		THUMBNAIL_SIZE: 150,
	},
	/** 分页配置 */
	PAGINATION: {
		DEFAULT_PAGE: 1,
		DEFAULT_LIMIT: 50,
		PAGE_SIZES: [20, 50, 100, 200],
		PAGER_COUNT: 5,
	},
	/** 列宽配置 */
	COLUMN_WIDTH: {
		MIN_WIDTH: 60,
		MAX_AUTO_WIDTH: 150,
		TITLE_CHAR_WIDTH: 12,
		PADDING: 40,
		// 不同类型的默认宽度
		TYPE_WIDTHS: {
			switch: 80,
			image: 100,
			date: 140,
			textbox: 120,
			combobox: 120,
		} as Record<string, number>,
	},
	/** 表格密度阈值 */
	DENSITY: {
		LESS_COLUMNS_THRESHOLD: 4,
		MORE_COLUMNS_THRESHOLD: 20,
	},
} as const;

/** 本地存储键名常量 */
const STORAGE_KEYS = {
	TABLE_SETTINGS: 'all-table-settings',
	TABLE_DENSITY: 'table-density',
} as const;

// ============ TypeScript 类型定义 ============

/**
 * 表格列配置接口
 *
 * 定义了表格每一列的完整配置选项，支持多种数据类型和显示模式。
 * 通过配置不同的属性，可以实现文本、图片、开关、下拉框等各种列类型。
 *
 * 【使用示例】
 * ```typescript
 * const columns: TableColumn[] = [
 *   {
 *     key: 'name',
 *     title: '姓名',
 *     type: 'text',
 *     width: 120,
 *     sortable: true
 *   },
 *   {
 *     key: 'avatar',
 *     title: '头像',
 *     type: 'image',
 *     imageWidth: 60,
 *     imageHeight: 60
 *   },
 *   {
 *     key: 'status',
 *     title: '状态',
 *     type: 'tag',
 *     tagType: (row, value) => value === 'active' ? 'success' : 'danger'
 *   }
 * ];
 * ```
 *
 * 【列类型支持】
 * - text: 普通文本显示（默认）
 * - switch: 开关控件，支持编辑模式
 * - image: 单张图片显示，支持预览
 * - base64-image: Base64图片显示
 * - imageList: 图片列表，支持多图展示
 * - textbox: 文本输入框（编辑模式）
 * - combobox: 下拉选择框（编辑模式）
 * - date: 日期时间选择器（编辑模式）
 * - icon: 图标显示
 * - file: 文件下载链接
 * - tag: 标签显示，支持不同主题色
 */
interface TableColumn {
	/** 列的唯一标识符，对应数据对象的属性名 */
	key: string;
	/** 列标题，显示在表头 */
	title: string;
	/** 列类型，决定该列的显示和交互方式 */
	type?: 'text' | 'switch' | 'image' | 'base64-image' | 'imageList' | 'filePreview' | 'textbox' | 'combobox' | 'date' | 'icon' | 'file' | 'tag';
	/** 列宽度，可以是像素值或百分比 */
	colWidth?: string | number;
	/** 列宽度（别名），可以是像素值或百分比 */
	width?: string | number;
	/** 用户调整后的列宽度，优先级最高 */
	userWidth?: string | number;
	/** 列最小宽度 */
	minWidth?: string | number;
	/** 列对齐方式 */
	align?: 'left' | 'center' | 'right';
	/** 是否在列设置中默认选中显示 */
	isCheck?: boolean;
	/** 是否被永久隐藏（优先级最高，隐藏后不可在列表中勾选） */
	isPermanentlyHidden?: boolean;
	/** 是否禁用该列的编辑功能 */
	isDisabled?: boolean;
	/** 是否启用排序功能 */
	sortable?: boolean;
	/** 列固定位置 */
	fixed?: 'left' | 'right' | boolean;
	/** 自定义格式化函数，用于处理显示内容 */
	formatter?: (row: any, value?: any) => string;
	/** 下拉框数据源，可以是静态对象或API接口地址 */
	comboData?: Record<string, string> | string;
	/** 图片显示宽度（像素） */
	imageWidth?: number;
	/** 图片显示高度（像素） */
	imageHeight?: number;
	/** 图片列表默认显示数量 */
	imageListCount?: number;
	/** 文件预览默认显示数量 */
	filePreviewCount?: number;
	/** 日期选择器类型 */
	dateType?: 'date' | 'month' | 'year' | 'week' | 'datetime' | 'time';
	/** 输入框占位符文本 */
	placeholder?: string;
	/** 文本输入最大长度限制 */
	maxlength?: number;
	/** 下拉框是否可清空 */
	clearable?: boolean;
	/** 文本是否截断显示 */
	truncate?: boolean;
	// 标签相关属性
	/** 标签类型，可以是固定值或函数 */
	tagType?: 'success' | 'danger' | 'warning' | 'info' | 'primary' | ((row: any, value: any) => 'success' | 'danger' | 'warning' | 'info' | 'primary');
	/** 标签大小 */
	tagSize?: 'large' | 'default' | 'small';
	/** 标签主题效果 */
	tagEffect?: 'dark' | 'light' | 'plain';
	/** 标签自定义颜色，可以是固定值或函数 */
	tagColor?: string | ((row: any, value: any) => string);
	/** 标签是否为圆角，默认为false（方角） */
	tagRound?: boolean;
	/** 空值时显示的文本 */
	emptyText?: string;
	/** 是否以链接样式显示，若提供 onClick 将自动视为可点击 */
	link?: boolean;
	/** 单元格点击回调，参数：当前行、当前值、列配置 */
	onClick?: (row: any, value: any, column: TableColumn) => void;
	/** 统计配置 */
	summary?: {
		/** 是否显示合计 */
		sum?: boolean;
		/** 是否显示平均值 */
		avg?: boolean;
		/** 是否显示最大值 */
		max?: boolean;
		/** 是否显示最小值 */
		min?: boolean;
		/** 是否显示计数 */
		count?: boolean;
		/** 自定义统计函数 */
		custom?: (values: any[]) => string;
		/** 统计标签 */
		label?: string;
	};
	/** 是否支持行内编辑 */
	editable?: boolean;
	/** 编辑时的控件类型 */
	editType?: 'textbox' | 'combobox' | 'date';
}

interface TableConfig {
	/** 数据总数，用于分页显示 */
	total?: number;
	/** 是否显示加载状态 */
	loading?: boolean;
	/** 是否显示表格边框 */
	isBorder?: boolean;
	/** 是否显示序号列 */
	isSerialNo?: boolean;
	/** 是否显示多选框列 */
	isSelection?: boolean;
	/** 是否显示操作列 */
	isOperate?: boolean;
	/** 是否禁用所有编辑功能 */
	isDisabled?: boolean;
	/** 是否为子表格模式 */
	isSub?: boolean;
	/** 是否开启斑马纹 */
	isStripe?: boolean;
	/** 是否隐藏分页组件 */
	hidePagination?: boolean;
	/** 是否隐藏设置按钮 */
	hideSetting?: boolean;
	/** 是否隐藏打印按钮 */
	hidePrint?: boolean;
	/** 是否隐藏刷新按钮 */
	hideRefresh?: boolean;
	/** 是否隐藏密度切换按钮 */
	hideDensity?: boolean;
	/** 表格唯一标识符，用于个性化设置存储 */
	settingsKey?: string;
	/** 是否显示统计行 */
	showSummary?: boolean;
	/** 是否显示计算按钮 */
	showCalculateBtn?: boolean;
	/** 计算接口地址 */
	calculateApi?: string;
	/** 统计行标题 */
	summaryText?: string;
	/** 单元格合并配置 */
	spanMethod?: (params: { row: any; column: any; rowIndex: number; columnIndex: number }) => [number, number] | void;
	/** 合并字段列表 - 根据这些字段的值相同来合并行 */
	mergeFields?: string[];
	/** 下拉框数据 */
	comboData?: ComboData;
}

interface SearchParams {
	/** 当前页码 */
	Page: number;
	/** 每页显示数量 */
	Limit: number;
	/** 排序信息 */
	SortInfo?: {
		/** 排序字段名 */
		Property: string;
		/** 排序方向：升序或降序 */
		Direction: 'Asc' | 'Desc';
	} | null;
}

interface ComboData {
	/** 下拉框数据字典，key为列名，value为选项数据 */
	[key: string]: Record<string, string>;
}

interface TableState {
	/** 搜索参数 */
	searcher: SearchParams;
	/** 表格数据 */
	data: any[];
	/** 图片预览列表 */
	picList: string[];
	/** 文件预览列表 */
	previewList: string[];
	/** 当前选中的行数据 */
	selectlist: any[];
	/** 列设置全选状态 */
	checkListAll: boolean;
	/** 列设置半选状态 */
	checkListIndeterminate: boolean;
	/** 下拉框数据缓存 */
	comboData: ComboData;
	/** 统计数据 */
	summaryData: Record<string, any>;
	/** 计算按钮加载状态 */
	calculating: boolean;
	/** 行编辑状态 */
	editingRows: Set<number>;
	/** 编辑前的原始数据备份 */
	originalData: Map<number, any>;
}

/** 表格尺寸类型：默认、紧凑、舒适 */
type TableSize = 'default' | 'small' | 'large';

// 定义 emits
const emit = defineEmits<{
	'update:modelValue': [value: any[]];
	'update:config': [config: TableConfig];
	cellChange: [rowIndex: number, column: string, value: any, type: string];
	rowEdit: [rowIndex: number, rowData: any];
	rowSave: [rowIndex: number, rowData: any, originalData: any];
	rowCancel: [rowIndex: number, originalData: any];
	batchSave: [editedRows: Array<{ index: number; data: any; original: any }>];
}>();

// 定义父组件传过来的值
const props = withDefaults(
	defineProps<{
		data?: any[];
		header?: TableColumn[];
		config?: TableConfig;
		modelValue?: any[];
		spanMethod?: (params: { row: any; column: any; rowIndex: number; columnIndex: number }) => [number, number] | void;
		[key: string]: any; // 允许额外的属性，支持v-bind传入整个对象
	}>(),
	{
		data: () => [],
		header: () => [],
		config: () => ({ isBorder: true }), // 默认开启边框
		modelValue: () => [],
	}
);

const listvalue = computed({
	get() {
		return props.modelValue || [];
	},
	set(value) {
		emit('update:modelValue', value);
	},
});

// 定义变量内容
const toolSetRef = ref<HTMLElement>();
const forPrint = ref<HTMLElement>();
const elTableRef = ref();
const router = useRouter();
const state = reactive<TableState>({
	searcher: {
		Page: TABLE_CONSTANTS.PAGINATION.DEFAULT_PAGE,
		Limit: TABLE_CONSTANTS.PAGINATION.DEFAULT_LIMIT,
		SortInfo: null,
	},
	data: props.data || [],
	picList: [],
	previewList: [],
	selectlist: [],
	checkListAll: true,
	checkListIndeterminate: false,
	comboData: props.config?.comboData || {},
	summaryData: {},
	calculating: false,
	editingRows: new Set<number>(),
	originalData: new Map<number, any>(),
});

// 新增默认配置对象
const defaultConfig: TableConfig = { isBorder: true, showSummary: false, showCalculateBtn: false };

// 创建本地配置副本，合并默认值，避免直接修改props
const localConfig = ref<TableConfig>({ ...defaultConfig, ...props.config });
const localHeader = ref<TableColumn[]>([...(props.header || [])]);

// 表格密度状态
const tableSize = ref<TableSize>('small');

// 表格强制刷新key
const tableKey = ref<number>(0);

// 文件预览对话框状态
const filePreviewVisible = ref<boolean>(false);
const currentPreviewFiles = ref<any[]>([]);
const currentPreviewIndex = ref<number>(0);
const pdfLoadError = ref<boolean>(false);
const isLoadingPreview = ref<boolean>(false);

// 分页大小选项 - 使用常量配置
const pageSizes = computed(() => TABLE_CONSTANTS.PAGINATION.PAGE_SIZES);

// 密度相关计算属性
const densityText = computed(() => {
	const map = {
		small: '紧凑',
		default: '标准',
		large: '舒适',
	};
	return map[tableSize.value];
});

const densityTooltipText = computed(() => {
	const map = {
		small: '切换到标准模式',
		default: '切换到舒适模式',
		large: '切换到紧凑模式',
	};
	return map[tableSize.value];
});

// 表格配置管理 - 使用常量
const { TABLE_SETTINGS, TABLE_DENSITY } = STORAGE_KEYS;

// ============ 工具函数 ============

/**
 * 清理过期的表格设置（超过2天未使用的设置）
 */
const cleanupExpiredSettings = (): void => {
	try {
		const allSettings = getAllTableSettings();
		const now = Date.now();
		const thirtyDaysAgo = now - 2 * 24 * 60 * 60 * 1000; // 2天前
		let hasChanges = false;

		Object.keys(allSettings).forEach((key) => {
			const setting = allSettings[key];
			// 如果设置没有lastUsed时间戳，或者超过2天未使用，则删除
			if (!setting?.lastUsed || setting.lastUsed < thirtyDaysAgo) {
				delete allSettings[key];
				hasChanges = true;
			}
		});

		if (hasChanges) {
			localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettings));
		}
	} catch (error) {
		// 清理过期设置失败
	}
};

/**
 * 将各种类型的值转换为布尔值
 * 支持字符串 'true'/'false' 和布尔值的转换
 */
const convertToBoolean = (value: any): boolean => {
	return !!(value && (value === true || value === 'true'));
};

/**
 * 格式化表格显示值
 * 根据数据类型和列配置进行智能格式化
 * @param value - 要格式化的值
 * @param column - 列配置信息
 */
const formatDisplayValue = (value: any, column: TableColumn): string => {
	// 处理空值
	if (value === null || value === undefined) return '';

	// 处理布尔值
	if (typeof value === 'boolean') return value ? '是' : '否';

	// 处理日期类型
	if (column.type === 'date' && value) {
		try {
			return new Date(value).toLocaleString();
		} catch {
			return String(value);
		}
	}

	// 默认转换为字符串
	return String(value);
};

// 生成表格唯一标识key，支持自定义settingsKey或基于表头生成
const getTableKey = (): string => {
	// 如果传入了自定义的settingsKey，优先使用
	if (localConfig.value.settingsKey) {
		return localConfig.value.settingsKey;
	}

	// 基于表头列的key生成唯一标识，结构相同的表格也重新生成key
	const headerKeys = (props.header || [])
		.map((h) => h.key)
		.sort()
		.join('_');

	// 获取当前路由信息作为额外标识
	const route = router?.currentRoute?.value;
	const routeIdentifier = route?.name || route?.path || 'unknown';

	if (headerKeys) {
		// 组合表头keys和路由信息，确保相同结构的表格在不同页面有不同的key
		const combinedKey = `${String(routeIdentifier)}_${headerKeys}`;
		return `table_${btoa(combinedKey)
			.replace(/[^a-zA-Z0-9]/g, '')
			.substr(0, 16)}`;
	}

	// 最后的fallback：使用时间戳
	return `table_${Date.now()}`;
};

// 获取所有表格设置 - 使用常量
const getAllTableSettings = (): Record<string, any> => {
	try {
		const settings = localStorage.getItem(TABLE_SETTINGS);
		return settings ? JSON.parse(settings) : {};
	} catch (error) {
		// Failed to parse table settings from localStorage
		return {};
	}
};

// 保存表格设置 - 使用常量
const saveTableSettings = (settings: any): void => {
	try {
		const allSettings = getAllTableSettings();
		const tableKey = getTableKey();

		// 保留现有的 dragSaveTimestamp（如果存在），这样用户拖拽调整的顺序不会被覆盖
		const existingSettings = allSettings[tableKey] || {};
		const dragSaveTimestamp = existingSettings.dragSaveTimestamp;

		// 添加时间戳标记使用时间
		const settingsWithTimestamp = {
			...settings,
			lastUsed: Date.now(),
			// 如果存在用户自定义的列顺序时间戳，保留它
			...(dragSaveTimestamp ? { dragSaveTimestamp } : {}),
		};

		allSettings[tableKey] = settingsWithTimestamp;
		localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettings));
	} catch (error) {
		// Failed to save table settings to localStorage
	}
};

// 获取当前表格的设置
const getCurrentTableSettings = () => {
	const allSettings = getAllTableSettings();
	const tableKey = getTableKey();
	const currentSettings = allSettings[tableKey] || null;

	// 更新使用时间戳
	if (currentSettings) {
		// 保存 dragSaveTimestamp，避免被覆盖
		const dragSaveTimestamp = currentSettings.dragSaveTimestamp;
		currentSettings.lastUsed = Date.now();
		// 异步更新，避免阻塞主流程
		setTimeout(() => {
			try {
				// 确保保留 dragSaveTimestamp
				if (dragSaveTimestamp !== undefined) {
					currentSettings.dragSaveTimestamp = dragSaveTimestamp;
				}
				allSettings[tableKey] = currentSettings;
				localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettings));
			} catch (error) {
				// 静默失败
			}
		}, 0);
	}

	return currentSettings;
};

// 保存列宽设置
const saveColumnWidths = (): void => {
	try {
		const columnWidths: Record<string, number> = {};
		localHeader.value.forEach((column) => {
			if (column.userWidth) {
				columnWidths[column.key] = typeof column.userWidth === 'string' ? parseInt(column.userWidth) : column.userWidth;
			}
		});

		// 获取现有设置并更新列宽信息
		const currentSettings = getCurrentTableSettings() || {};
		currentSettings.columnWidths = columnWidths;

		// 保存到localStorage
		const allSettings = getAllTableSettings();
		allSettings[getTableKey()] = currentSettings;
		localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettings));
	} catch (error) {
		// Failed to save column widths to localStorage
	}
};

// 恢复列宽设置
const restoreColumnWidths = (): void => {
	try {
		const settings = getCurrentTableSettings();
		if (settings && settings.columnWidths) {
			localHeader.value.forEach((column) => {
				const savedWidth = settings.columnWidths[column.key];
				if (savedWidth) {
					column.userWidth = savedWidth;
				}
			});
		}
	} catch (error) {
		// Failed to restore column widths from localStorage
	}
};

// 保存永久隐藏列设置
const savePermanentlyHiddenColumns = (): void => {
	try {
		const hiddenColumns: string[] = [];
		localHeader.value.forEach((column) => {
			if (column.isPermanentlyHidden) {
				hiddenColumns.push(column.key);
			}
		});

		// 获取现有设置并更新永久隐藏列信息
		const currentSettings = getCurrentTableSettings() || {};
		currentSettings.permanentlyHiddenColumns = hiddenColumns;

		// 保存到localStorage
		const allSettings = getAllTableSettings();
		allSettings[getTableKey()] = currentSettings;
		localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettings));
	} catch (error) {
		// Failed to save permanently hidden columns to localStorage
	}
};

// 标志位：防止拖拽保存后被watch覆盖
let isDraggingSave = false;
// 标志位：是否已经执行过列顺序恢复
let hasRestoredColumnOrder = false;
// 上次拖拽保存的时间戳，用于更精确的冲突避免
let lastDragSaveTime = 0;

// 保存列顺序设置
const saveColumnOrder = (): void => {
	try {
		const columnOrder: string[] = [];
		localHeader.value.forEach((column) => {
			columnOrder.push(column.key);
		});

		// 记录拖拽保存时间戳
		lastDragSaveTime = Date.now();

		// 直接获取原始设置，避免调用 getCurrentTableSettings() 导致异步保存覆盖 dragSaveTimestamp
		const allSettings = getAllTableSettings();
		const tableKey = getTableKey();
		const currentSettings = allSettings[tableKey] || {};

		// 保持其他设置不变，只更新列顺序
		const newSettings = {
			isOperate: currentSettings.isOperate ?? localConfig.value.isOperate,
			isSerialNo: currentSettings.isSerialNo ?? localConfig.value.isSerialNo,
			isSelection: currentSettings.isSelection ?? localConfig.value.isSelection,
			columnSettings: currentSettings.columnSettings || {},
			columnWidths: currentSettings.columnWidths || {},
			permanentlyHiddenColumns: currentSettings.permanentlyHiddenColumns || [],
			columnOrder: columnOrder,
			// 添加保存时间戳，用于识别最新的拖拽保存
			dragSaveTimestamp: lastDragSaveTime,
			// 保留 lastUsed 时间戳（如果存在）
			lastUsed: currentSettings.lastUsed || Date.now(),
		};

		allSettings[tableKey] = newSettings;
		localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettings));

		// 延长保护时间到1000ms，并添加时间戳验证
		setTimeout(() => {
			isDraggingSave = false;
		}, 1000);
	} catch (error) {
		// 拖拽保存失败
		isDraggingSave = false; // 发生错误时也要重置标志位
	}
};

// 恢复永久隐藏列设置
const restorePermanentlyHiddenColumns = (): void => {
	try {
		const settings = getCurrentTableSettings();
		if (settings && settings.permanentlyHiddenColumns) {
			localHeader.value.forEach((column) => {
				if (settings.permanentlyHiddenColumns.includes(column.key)) {
					column.isPermanentlyHidden = true;
					column.isCheck = false;
				}
			});
		}
	} catch (error) {
		// Failed to restore permanently hidden columns from localStorage
	}
};

/**
 * 重置当前表的个性化设置（仅清除当前表对应的 all-table-settings 项）
 * 包括：列顺序、列显示状态、列宽设置、永久隐藏状态
 */
const resetCurrentTableSettings = (): void => {
	try {
		// 确认操作
		ElMessageBox.confirm(
			'此操作将清除所有用户自定义设置，恢复到代码定义的默认状态，包括：\n• 列顺序\n• 列显示状态（isCheck）\n• 列宽\n• 永久隐藏状态\n\n是否继续？', 
			'确认重置', 
			{
				confirmButtonText: '确定',
				cancelButtonText: '取消',
				type: 'warning',
				dangerouslyUseHTMLString: false,
			}
		)
			.then(() => {
				// 设置标志位，防止watch在重置过程中保存设置
				isDraggingSave = true;
				lastDragSaveTime = Date.now();

				// 清除localStorage中的设置
				const allSettings = getAllTableSettings();
				const key = getTableKey();
				if (allSettings[key]) {
					delete allSettings[key];
					localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettings));
				}

				// 重置标志位
				hasRestoredColumnOrder = false;

				// 恢复到原始的props.header顺序和状态
				if (props.header && Array.isArray(props.header)) {
					// 深度复制原始header配置，使用代码定义的原始值
					const originalHeaders = props.header.map((header) => ({
						...header,
						// 使用代码定义的原始值
						isCheck: header.isCheck ?? true, // 如果未定义，默认为true
						isPermanentlyHidden: false,
						userWidth: undefined,
					}));

					// 显示成功消息
					ElMessage.success('表格设置已重置，页面即将刷新');
					
					// 延迟刷新页面，确保用户看到成功消息
					setTimeout(() => {
						window.location.reload();
					}, 500);
				} else {
					// 显示成功消息
					ElMessage.success('表格设置已重置，页面即将刷新');
					
					// 延迟刷新页面
					setTimeout(() => {
						window.location.reload();
					}, 500);
				}

				// 延迟重置标志位，确保watch不会在重置后立即保存
				setTimeout(() => {
					// 再次清除localStorage，确保没有旧数据
					const allSettingsAfter = getAllTableSettings();
					if (allSettingsAfter[key]) {
						delete allSettingsAfter[key];
						localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettingsAfter));
					}

					// 重置标志位
					isDraggingSave = false;
					lastDragSaveTime = 0;
				}, 2000); // 2秒后重置标志位，确保watch已经执行完毕
			})
			.catch(() => {
				// 用户取消操作
				ElMessage.info('已取消重置操作');
			});
	} catch (error) {
		// 重置表格设置失败
		ElMessage.error('重置失败，请重试');
	}
};

// ============ 统一的事件处理函数 ============

/**
 * 统一的单元格变化事件处理函数
 * 减少重复代码，所有类型的单元格变化都通过此函数处理
 * @param rowIndex - 行索引
 * @param column - 列标识
 * @param value - 新值
 * @param type - 控件类型
 */
const handleCellChange = (rowIndex: number, column: string, value: any, type: string): void => {
	emit('cellChange', rowIndex, column, value, type);
};

// 各类型控件的事件处理函数 - 统一调用handleCellChange
const onSwitchChange = (rowIndex: number, column: string, value: boolean): void => handleCellChange(rowIndex, column, value, 'switch');
const onInputChange = (rowIndex: number, column: string, value: string): void => handleCellChange(rowIndex, column, value, 'textbox');
const onSelectChange = (rowIndex: number, column: string, value: any): void => handleCellChange(rowIndex, column, value, 'combobox');
const onDateChange = (rowIndex: number, column: string, value: Date): void => handleCellChange(rowIndex, column, value, 'date');
const onTimeChange = (rowIndex: number, column: string, value: Date): void => handleCellChange(rowIndex, column, value, 'time');

// ============ 行编辑功能 ============

/**
 * 开始编辑行
 * @param rowIndex - 行索引
 */
const startRowEdit = (rowIndex: number): void => {
	try {
		// 备份原始数据
		const dataSource = props.config?.isSub === true ? listvalue.value : state.data;
		state.originalData.set(rowIndex, { ...dataSource[rowIndex] });

		// 标记为编辑状态
		state.editingRows.add(rowIndex);

		// 触发编辑事件
		emit('rowEdit', rowIndex, dataSource[rowIndex]);
	} catch (error) {
		// 开始编辑行失败
	}
};

/**
 * 保存行编辑
 * @param rowIndex - 行索引
 */
const saveRowEdit = (rowIndex: number): void => {
	try {
		const dataSource = props.config?.isSub === true ? listvalue.value : state.data;
		const originalData = state.originalData.get(rowIndex);

		if (!originalData) {
			return;
		}

		// 触发保存事件
		emit('rowSave', rowIndex, { ...dataSource[rowIndex] }, originalData);

		// 清除编辑状态
		state.editingRows.delete(rowIndex);
		state.originalData.delete(rowIndex);
	} catch (error) {
		// 保存行编辑失败
	}
};

/**
 * 取消行编辑
 * @param rowIndex - 行索引
 */
const cancelRowEdit = (rowIndex: number): void => {
	try {
		const originalData = state.originalData.get(rowIndex);

		if (originalData) {
			// 恢复原始数据
			const dataSource = props.config?.isSub === true ? listvalue.value : state.data;
			Object.assign(dataSource[rowIndex], originalData);

			// 触发取消事件
			emit('rowCancel', rowIndex, originalData);
		}

		// 清除编辑状态
		state.editingRows.delete(rowIndex);
		state.originalData.delete(rowIndex);
	} catch (error) {
		// 取消行编辑失败
	}
};

/**
 * 批量保存所有编辑的行
 */
const batchSaveAll = (): void => {
	try {
		const editedRows: Array<{ index: number; data: any; original: any }> = [];
		const dataSource = props.config?.isSub === true ? listvalue.value : state.data;

		// 收集所有编辑的行数据
		state.editingRows.forEach((rowIndex) => {
			const originalData = state.originalData.get(rowIndex);
			if (originalData) {
				editedRows.push({
					index: rowIndex,
					data: { ...dataSource[rowIndex] },
					original: originalData,
				});
			}
		});

		// 触发批量保存事件
		emit('batchSave', editedRows);

		// 清除所有编辑状态
		state.editingRows.clear();
		state.originalData.clear();
	} catch (error) {
		// 批量保存失败
	}
};

/**
 * 取消所有行编辑
 */
const cancelAllEdit = (): void => {
	try {
		const dataSource = props.config?.isSub === true ? listvalue.value : state.data;

		// 恢复所有行的原始数据
		state.editingRows.forEach((rowIndex) => {
			const originalData = state.originalData.get(rowIndex);
			if (originalData) {
				Object.assign(dataSource[rowIndex], originalData);
			}
		});

		// 清除所有编辑状态
		state.editingRows.clear();
		state.originalData.clear();
	} catch (error) {
		// 取消所有编辑失败
	}
};

/**
 * 获取表格行的CSS类名
 * @param param - 行参数对象
 * @returns CSS类名字符串
 */
const getRowClassName = ({ rowIndex }: { row: any; rowIndex: number }): string => {
	return state.editingRows.has(rowIndex) ? 'editing-row' : '';
};

// ============ 响应式数据监听 ============

/**
 * 监听父组件传入的数据变化
 * 当父组件的data发生变化时，同步更新本地数据
 */
watch(
	() => props.data,
	(newData) => {
		if (newData) {
			state.data = [...newData];
		}
	},
	{ deep: true, immediate: true }
);

/**
 * 监听父组件传入的配置变化
 * 当父组件的config发生变化时，同步更新本地配置
 */
watch(
	() => props.config,
	(newConfig) => {
		if (newConfig) {
			localConfig.value = { ...newConfig };
			// 更新下拉框数据
			if (newConfig.comboData) {
				state.comboData = { ...newConfig.comboData };
			}
		}
	},
	{ deep: true }
);

/**
 * 监听父组件传入的表头配置变化
 * 当父组件的header发生变化时，同步更新本地表头配置
 * 使用深度监听确保isCheck等属性变化时能触发watch
 */
watch(
	() => props.header,
	(newHeader) => {
		if (newHeader && newHeader.length > 0) {
			// 检查是否有已保存的列顺序
			const settings = getCurrentTableSettings();

			// 获取代码定义的列顺序（newHeader 的顺序）
			const codeDefinedOrder = newHeader.map((col) => col.key).filter((key) => key);

			// 如果存在 dragSaveTimestamp，说明用户曾经拖拽调整过列顺序，应该始终使用保存的顺序
			const hasUserCustomOrder = settings && settings.dragSaveTimestamp;
			
			// 检查保存的顺序是否有效（至少要有保存的列顺序数组）
			const hasSavedOrder = 
				settings &&
				settings.columnOrder &&
				Array.isArray(settings.columnOrder) &&
				settings.columnOrder.length > 0;

			// 如果用户有自定义顺序，始终使用保存的顺序
			if (hasUserCustomOrder && hasSavedOrder) {
				// 按照保存的顺序重新排列列
				const orderedHeaders: TableColumn[] = [];
				const headerMap = new Map<string, TableColumn>();

				// 创建key到列对象的映射（使用新的header数据）
				newHeader.forEach((column) => {
					headerMap.set(column.key, column);
				});

				// 获取保存的列显示状态
				const savedColumnStates = settings.columnStates || {};

				// 按保存的顺序添加列（只添加当前存在的列）
				settings.columnOrder.forEach((key: string) => {
					const column = headerMap.get(key);
					if (column) {
						// 查找是否有现有的状态需要保持
						const existingColumn = localHeader.value.find((c) => c.key === key);
						const savedState = savedColumnStates[key];
						
						// 检查代码定义的isCheck是否与保存的不同
						// 如果不同，说明开发者修改了代码，应该使用代码定义的值
						const codeIsCheckChanged = savedState && column.isCheck !== undefined && savedState.isCheck !== column.isCheck;
						
						orderedHeaders.push({
							...column,
							// isCheck优先级：代码修改了 > 用户保存的状态 > 现有状态 > 代码定义的默认值
							isCheck: codeIsCheckChanged ? column.isCheck : (savedState?.isCheck ?? existingColumn?.isCheck ?? column.isCheck),
							isPermanentlyHidden: savedState?.isPermanentlyHidden ?? existingColumn?.isPermanentlyHidden ?? column.isPermanentlyHidden,
							userWidth: savedState?.userWidth ?? existingColumn?.userWidth ?? column.userWidth,
						});
						headerMap.delete(key);
					}
				});

				// 添加任何新的列到末尾（保存的顺序中不存在的新列，使用代码定义的默认值）
				headerMap.forEach((column) => {
					orderedHeaders.push(column);
				});

				localHeader.value = orderedHeaders;
			} else {
				// 使用代码定义的顺序
				localHeader.value = [...newHeader];
			}
		}
	},
	{ deep: true, flush: 'post' }
);

/**
 * 监听本地配置和表头变化，执行以下操作：
 * 1. 向父组件同步配置变化
 * 2. 保存用户个性化设置到localStorage
 */
watch(
	[localConfig, localHeader],
	([newConfig, newHeader]) => {
		// 如果正在拖拽保存，跳过此次watch以避免覆盖拖拽结果
		if (isDraggingSave) {
			return;
		}

		// 检查是否刚刚进行了拖拽保存（1.5秒内），如果是则跳过
		const timeSinceLastDrag = Date.now() - lastDragSaveTime;
		if (timeSinceLastDrag < 1500) {
			return;
		}

		// 向父组件发送配置更新事件
		emit('update:config', newConfig);

		// 构建列显示设置对象
		const columnSettings: Record<string, boolean> = {};
		const columnWidths: Record<string, number> = {};
		const columnStates: Record<string, any> = {};
		const permanentlyHiddenColumns: string[] = [];
		const columnOrder: string[] = [];
		newHeader.forEach((column) => {
			columnSettings[column.key] = column.isCheck ?? true;
			columnOrder.push(column.key);
			
			// 保存完整的列状态
			columnStates[column.key] = {
				isCheck: column.isCheck ?? true,
				isPermanentlyHidden: column.isPermanentlyHidden ?? false,
				userWidth: column.userWidth,
			};
			
			if (column.isPermanentlyHidden) {
				permanentlyHiddenColumns.push(column.key);
			}
			// 保存用户调整的列宽
			if (column.userWidth) {
				columnWidths[column.key] = typeof column.userWidth === 'string' ? parseInt(column.userWidth) : column.userWidth;
			}
		});

		// 保存用户个性化设置到本地存储
		saveTableSettings({
			isOperate: newConfig.isOperate,
			isSerialNo: newConfig.isSerialNo,
			isSelection: newConfig.isSelection,
			columnSettings: columnSettings,
			columnWidths: columnWidths,
			columnStates: columnStates, // 新增：保存完整的列状态
			permanentlyHiddenColumns,
			columnOrder: columnOrder,
		});
	},
	{ deep: true }
);

let searchApi: Function = () => Promise.resolve({ Data: [], Count: 0 });
let isTreeState: any = null;

/**
 * 设置表格边框显示/隐藏
 * 从配置中读取边框设置，默认为false（无边框）
 */
const setBorder = computed(() => {
	return localConfig.value.isBorder ?? false;
});

/**
 * 检查是否有可编辑的列
 */
const hasEditableColumns = computed(() => {
	return localHeader.value.some((column) => column.editable === true);
});

/**
 * 处理下拉框选项值的类型转换
 * 将字符串形式的布尔值转换为真正的布尔类型
 * @param key - 选项的key值，可能是字符串、数字或布尔值
 * @returns 转换后的值：'true'/'false' -> boolean，其他保持原类型
 */
const getComboValue = (key: string | number): string | number | boolean => {
	if (key === 'true' || String(key) === 'true') {
		return true;
	} else if (key === 'false' || String(key) === 'false') {
		return false;
	} else {
		return key;
	}
};

// ============ 计算属性 ============

/**
 * 获取当前显示的表头列
 * 过滤掉被用户隐藏的列（isCheck为false的列）
 */
const setHeader = computed(() => {
	// 过滤掉被永久隐藏或临时隐藏（isCheck=false）的列
	const result = localHeader.value.filter((v) => v.isPermanentlyHidden !== true && v.isCheck !== false);
	return result;
});

// 永久隐藏数量（用于按钮文本切换）
const permanentlyHiddenCount = computed(() => localHeader.value.filter((v) => v.isPermanentlyHidden).length);

/**
 * 智能判断表格列数情况，用于优化显示策略：
 * - 少列（≤4列）：让列自动撑满表格宽度，提供更好的视觉效果
 * - 多列（>20列）：使用紧凑布局并固定操作列，优化横向滚动体验
 */
const isLessColumns = computed(() => setHeader.value.length <= 4);
const isMoreColumns = computed(() => setHeader.value.length > 20);

/**
 * 智能列宽计算函数 - 优化后的版本
 * 根据列数情况和列类型智能分配宽度，减少条件嵌套
 * @param item - 列配置对象
 * @returns 计算后的列宽值
 */
const getColumnWidth = (item: TableColumn): string | number | undefined => {
	// 优先级1: 用户调整的宽度 > 配置的宽度
	const userDefinedWidth = item.userWidth || item.colWidth || item.width;
	if (userDefinedWidth) return userDefinedWidth;

	// 优先级2: 少列时让表格自动撑满，中等列数时使用默认宽度
	if (isLessColumns.value || !isMoreColumns.value) return undefined;

	// 优先级3: 多列时使用常量配置获取紧凑宽度
	const { TYPE_WIDTHS, MIN_WIDTH, MAX_AUTO_WIDTH, TITLE_CHAR_WIDTH, PADDING } = TABLE_CONSTANTS.COLUMN_WIDTH;

	// 如果有预定义的类型宽度，直接返回
	if (item.type && TYPE_WIDTHS[item.type]) {
		return TYPE_WIDTHS[item.type];
	}

	// 否则根据标题长度动态计算，限制在合理范围内
	const titleLength = item.title?.length || 5;
	const calculatedWidth = titleLength * TITLE_CHAR_WIDTH + PADDING;
	return Math.max(MIN_WIDTH, Math.min(calculatedWidth, MAX_AUTO_WIDTH));
};

// 获取列最小宽度
const getColumnMinWidth = (item: TableColumn): string | number | undefined => {
	// 如果设置了最小宽度，使用设置的值
	if (item.minWidth) return item.minWidth;

	// 根据列类型设置默认最小宽度
	switch (item.type) {
		case 'switch':
			return 60;
		case 'image':
			return 80;
		case 'date':
			return 120;
		case 'textbox':
		case 'combobox':
			return 100;
		default:
			// 根据标题长度计算最小宽度，但不少于60px
			const titleWidth = (item.title?.length || 3) * 12 + 30;
			return Math.max(60, titleWidth);
	}
};

/**
 * 标题显示优化 - 长标题自动换行或省略
 * 根据列数情况智能处理标题显示：多列时截断长标题避免表格过宽
 * @param title - 原始标题文本
 * @returns 处理后的标题文本
 */
const getDisplayTitle = (title?: string): string => {
	if (!title) return '';

	// 多列时截断长标题，避免表格过宽影响用户体验
	if (isMoreColumns.value && title.length > 6) {
		return title.substring(0, 6) + '...';
	}

	return title;
};

// ============ 表格设置相关事件处理 ============

/**
 * 列显示全选状态改变处理
 * 当用户点击"全选"复选框时触发
 * @param val - 是否全选
 */
const onCheckAllChange = (val: boolean): void => {
	if (val) {
		localHeader.value.forEach((v) => {
			if (!v.isPermanentlyHidden) v.isCheck = true;
		});
	} else {
		localHeader.value.forEach((v) => {
			if (!v.isPermanentlyHidden) v.isCheck = false;
		});
	}
	state.checkListIndeterminate = false;
};

/**
 * 单个列显示状态改变处理
 * 当用户切换单个列的显示状态时触发，更新全选状态
 */
const onCheckChange = (): void => {
	const visibleHeaders = localHeader.value.filter((v) => v.isCheck && !v.isPermanentlyHidden).length;
	const totalHeaders = localHeader.value.filter((v) => !v.isPermanentlyHidden).length;
	state.checkListAll = visibleHeaders === totalHeaders;
	state.checkListIndeterminate = visibleHeaders > 0 && visibleHeaders < totalHeaders;
};

// 删除重复实现：以避免变量重复声明

/**
 * 批量将未勾选的列设置为永久隐藏
 */
const bulkHideUncheckedColumns = (): void => {
	let changed = 0;
	localHeader.value.forEach((col) => {
		if (!col.isCheck) {
			col.isPermanentlyHidden = true;
			col.isCheck = false;
			changed++;
		}
	});
	if (changed > 0) {
		savePermanentlyHiddenColumns();
		onCheckChange();
		ElMessage.success(`已永久隐藏 ${changed} 列`);
	} else {
		ElMessage.info('没有未勾选的列需要隐藏');
	}
};

/**
 * 批量取消所有永久隐藏的列
 */
const bulkUnhideAllColumns = (): void => {
	let changed = 0;
	localHeader.value.forEach((col) => {
		if (col.isPermanentlyHidden) {
			col.isPermanentlyHidden = false;
			// 不强制勾选，保持用户当前 isCheck 选择
			changed++;
		}
	});
	if (changed > 0) {
		savePermanentlyHiddenColumns();
		onCheckChange();
		ElMessage.success('已取消所有永久隐藏');
	} else {
		ElMessage.info('当前没有永久隐藏的列');
	}
};

/**
 * 切换永久隐藏：
 * - 如果存在任何永久隐藏列，则取消所有永久隐藏
 * - 否则，将当前未勾选的列永久隐藏
 */
const togglePermanentHide = (): void => {
	if (permanentlyHiddenCount.value > 0) {
		bulkUnhideAllColumns();
	} else {
		bulkHideUncheckedColumns();
	}
};

// ============ 表格交互事件处理 ============

/**
 * 表格多选状态改变处理
 * 当用户选择或取消选择表格行时触发，用于批量操作和导出功能
 * @param val - 当前选中的行数据数组
 */
const onSelectionChange = (val: any[]): void => {
	state.selectlist = val;
};

/**
 * 表格排序改变处理
 * 当用户点击列头进行排序时触发，自动重新搜索数据
 * @param columninfo - 排序信息，包含列名和排序方向
 */
const onSortChange = (columninfo: any): void => {
	if (columninfo.prop && columninfo.order) {
		state.searcher.SortInfo = {
			Property: columninfo.prop,
			Direction: columninfo.order === 'descending' ? 'Desc' : 'Asc',
		};
	} else {
		state.searcher.SortInfo = null;
	}
	doSearch();
};

/**
 * 列宽调整处理
 * 当用户拖拽调整列宽时触发，保存用户调整的列宽
 * @param newWidth - 新的列宽
 * @param oldWidth - 原来的列宽
 * @param column - 列信息
 * @param event - 事件对象
 */
const onColumnResize = (newWidth: number, oldWidth: number, column: any, event: Event): void => {
	try {
		// 查找对应的列配置
		const targetColumn = localHeader.value.find((item) => item.key === column.property);
		if (targetColumn) {
			// 保存用户调整的列宽
			targetColumn.userWidth = newWidth;

			// 保存列宽设置到localStorage
			saveColumnWidths();
		}
	} catch (error) {
		// 列宽调整失败
	}
};

/**
 * 统一的分页处理函数
 * 处理分页大小和页码变化，避免代码重复
 * @param type - 变化类型：'size' | 'page'
 * @param value - 新的值
 */
const handlePaginationChange = (type: 'size' | 'page', value: number): void => {
	// 更新对应的搜索参数
	if (type === 'size') {
		state.searcher.Limit = value;
	} else if (type === 'page') {
		state.searcher.Page = value;
	}

	// 清除选择状态，避免跨页选择混乱
	state.selectlist = [];
	// 重新搜索数据
	doSearch();
};

/**
 * 分页大小改变处理 - 简化版本
 * @param val - 新的每页显示数量
 */
const onHandleSizeChange = (val: number): void => handlePaginationChange('size', val);

/**
 * 当前页码改变处理 - 简化版本
 * @param val - 新的页码
 */
const onHandleCurrentChange = (val: number): void => handlePaginationChange('page', val);

/**
 * 初始化下拉框数据
 * 遍历所有combobox类型的列，加载其对应的选项数据
 * 支持两种数据源：
 * 1. 字符串类型：作为API接口地址，异步获取数据
 * 2. 对象类型：直接使用静态数据
 */
const initComboData = async (): Promise<void> => {
	// 筛选出所有下拉框类型的列
	const ch = localHeader.value.filter((item) => item.type === 'combobox');
	const rv: ComboData = {};

	// 逐个处理每个下拉框列的数据
	for (const element of ch) {
		let cd: Record<string, string> = {};

		// 处理API接口类型的数据源
		if (element.comboData && typeof element.comboData === 'string') {
			try {
				// 调用后台接口获取选项数据
				const data = await other.getSelectList(element.comboData, [], false);
				// 转换数据格式：将 {Value, Text} 数组转换为 {key: value} 对象
				data.forEach((x: any) => {
					cd[x.Value] = x.Text;
				});
			} catch (error) {
				// Failed to load combo data
				// 向用户显示友好的错误提示
				ElMessage.warning(`下拉选项 ${element.title} 加载失败`);
			}
		}
		// 处理静态对象类型的数据源
		else if (element.comboData && typeof element.comboData === 'object') {
			cd = element.comboData;
		}

		// 将处理后的数据存储到状态中
		rv[element.key] = cd;
	}

	// 批量更新状态，触发组件重新渲染
	state.comboData = rv;
};

// 窗口大小变化处理函数（已废弃，保留引用以防兼容性问题）
let handleResize: (() => void) | null = null;

/**
 * 组件挂载时的初始化逻辑
 * 包括：下拉框数据初始化、表格设置恢复、密度设置应用
 */
onMounted(() => {
	// 定期清理过期设置（避免启动时阻塞，随机延迟执行）
	const cleanupDelay = Math.random() * 10000 + 5000; // 5-15秒随机延迟
	setTimeout(() => {
		cleanupExpiredSettings();
	}, cleanupDelay);

	// 异步初始化下拉框数据，避免阻塞主要初始化流程
	initComboData().catch((error) => {
		// Failed to initialize combo data
	});

	// 恢复保存的表格设置（列显示状态、操作配置等）
	const settings = getCurrentTableSettings();

	// 无论是否存在列显示设置，优先恢复永久隐藏列
	restorePermanentlyHiddenColumns();

	if (settings) {
		// 恢复操作相关配置
		if (settings.isOperate !== undefined) {
			localConfig.value.isOperate = settings.isOperate;
		}
		if (settings.isSerialNo !== undefined) {
			localConfig.value.isSerialNo = settings.isSerialNo;
		}
		if (settings.isSelection !== undefined) {
			localConfig.value.isSelection = settings.isSelection;
		}

		// 恢复列显示状态配置
		if (settings.columnSettings) {
			// 先恢复永久隐藏列
			if (settings.permanentlyHiddenColumns && Array.isArray(settings.permanentlyHiddenColumns)) {
				localHeader.value.forEach((column) => {
					if (settings.permanentlyHiddenColumns.includes(column.key)) {
						column.isPermanentlyHidden = true;
						column.isCheck = false;
					} else {
						column.isPermanentlyHidden = false;
					}
				});
			}

			localHeader.value.forEach((column) => {
				const savedColumn = settings.columnSettings[column.key];
				if (savedColumn !== undefined) {
					column.isCheck = savedColumn;
				}
			});

			// 更新全选状态（忽略永久隐藏列）
			const visibleHeaders = localHeader.value.filter((v) => v.isCheck && !v.isPermanentlyHidden).length;
			const totalHeaders = localHeader.value.filter((v) => !v.isPermanentlyHidden).length;
			state.checkListAll = visibleHeaders === totalHeaders;
			state.checkListIndeterminate = visibleHeaders > 0 && visibleHeaders < totalHeaders;
		}

		// 恢复列宽设置
		if (settings.columnWidths) {
			localHeader.value.forEach((column) => {
				const savedWidth = settings.columnWidths[column.key];
				if (savedWidth) {
					column.userWidth = savedWidth;
				}
			});
		}
	}

	// 从localStorage读取并应用表格密度设置
	const savedDensity = localStorage.getItem('table-density');
	if (savedDensity && ['default', 'small', 'large'].includes(savedDensity)) {
		tableSize.value = savedDensity as TableSize;
	}

	// 恢复用户自定义的列顺序
	if (settings && settings.columnOrder && Array.isArray(settings.columnOrder) && settings.columnOrder.length > 0 && localHeader.value.length > 0) {
		// 如果存在 dragSaveTimestamp，说明用户曾经拖拽调整过列顺序，应该始终使用保存的顺序
		const hasUserCustomOrder = settings.dragSaveTimestamp;

		// 如果用户有自定义顺序，恢复保存的顺序
		if (hasUserCustomOrder) {
			const orderedHeaders: TableColumn[] = [];
			const headerMap = new Map<string, TableColumn>();

			// 创建key到列对象的映射
			localHeader.value.forEach((column) => {
				headerMap.set(column.key, column);
			});

			// 按保存的顺序添加列（只添加当前存在的列）
			settings.columnOrder.forEach((key: string) => {
				const column = headerMap.get(key);
				if (column) {
					orderedHeaders.push(column);
					headerMap.delete(key);
				}
			});

			// 添加任何新的列到末尾（保存的顺序中不存在的新列）
			headerMap.forEach((column) => {
				orderedHeaders.push(column);
			});

			if (orderedHeaders.length > 0) {
				localHeader.value = orderedHeaders;
			}
		}
	}
});

/**
 * 组件卸载时的清理工作
 * 移除事件监听器，防止内存泄漏
 */
onUnmounted(() => {
	// 清理窗口大小变化监听器（虽然已不使用，但保留清理逻辑）
	if (handleResize) {
		window.removeEventListener('resize', handleResize);
		handleResize = null;
	}

	// 清理拖拽状态（但不清理 hasRestoredColumnOrder，因为它需要在组件重新挂载时保持状态）
	dragStartIndex = -1;
	isDraggingSave = false;
	lastDragSaveTime = 0;
});

/**
 * 清除表格选择状态
 * 用于批量操作后重置选择状态
 */
const clearSelection = (): void => {
	elTableRef.value?.clearSelection();
};

/**
 * =====================================================================================
 * 核心数据搜索方法 - 表格数据加载的中枢
 * =====================================================================================
 *
 * 【方法概述】
 * 这是表格组件的核心方法，负责从后端API获取数据并进行预处理。
 * 支持普通表格和树形表格两种数据结构，自动处理图片URL生成、预览索引等。
 *
 * 【功能特性】
 * 1. 🔄 数据获取：调用后端API，传递分页、排序等参数
 * 2. 🖼️ 图片处理：自动为图片列生成缩略图URL和预览索引
 * 3. 🌲 树形支持：支持父子关系数据的树形结构构建
 * 4. 📊 状态管理：管理加载状态、选择状态等UI状态
 * 5. ⚡ 性能优化：图片预加载、数据缓存等性能优化措施
 *
 * 【使用场景】
 * - 页面首次加载数据
 * - 分页切换时加载数据
 * - 排序条件变更时重新加载
 * - 搜索条件变更时过滤数据
 * - 刷新按钮触发的数据重载
 *
 * 【调用示例】
 * ```typescript
 * // 基础用法
 * await doSearch(getUserListApi, { keyword: 'admin' });
 *
 * // 树形数据
 * await doSearch(getDeptTreeApi, null, true, 'ParentId');
 *
 * // 仅刷新当前数据
 * await doSearch();
 * ```
 *
 * 【参数说明】
 * @param api - 搜索API函数，如果为null则使用之前设置的API
 * @param para - 搜索参数对象，会与当前搜索条件合并
 * @param isTree - 是否为树形数据，影响数据的处理方式
 * @param parentKey - 树形数据的父级ID字段名，默认为'ParentId'
 *
 * 【返回值】
 * Promise<void> - 异步方法，成功完成数据加载或抛出异常
 *
 * 【异常处理】
 * - 网络错误：显示"数据加载失败"提示
 * - API错误：记录错误日志并显示用户友好提示
 * - 数据格式错误：自动降级处理，避免页面崩溃
 *
 * 【性能注意事项】
 * - 大数据集加载时会有Loading状态显示
 * - 图片URL生成采用懒加载策略
 * - 树形数据构建采用一次遍历算法，时间复杂度O(n)
 */
const doSearch = async (api: Function | null = null, para: any = null, isTree: any = null, parentKey: string = 'ParentId'): Promise<void> => {
	// 更新搜索参数
	if (para !== null) {
		Object.assign(state.searcher, para);
	}

	// 更新搜索API函数
	if (api != null) {
		searchApi = api;
	}

	// 更新树形状态
	if (isTree !== null) {
		isTreeState = isTree;
	}

	try {
		// 显示加载状态
		localConfig.value.loading = true;

		// 每次搜索前清空预览列表，避免索引错位
		state.picList = [];
		state.previewList = [];

		// 执行搜索请求
		const res: AxiosResponse<any, any> = await searchApi(state.searcher);

		// 清除之前的选择状态，避免数据更新后选择状态异常
		clearSelection();
		state.selectlist = [];

		const datatemp: any[] = [];
		// 获取所有图片类型的列，用于处理图片预览
		const imageHeaders = localHeader.value.filter((v) => v.isCheck && v.type === 'image');
		const base64ImageHeaders = localHeader.value.filter((v) => v.isCheck && v.type === 'base64-image');
		const imageListHeaders = localHeader.value.filter((v) => v.isCheck && v.type === 'imageList');
		const filePreviewHeaders = localHeader.value.filter((v) => v.isCheck && v.type === 'filePreview');
		let imageIndex = 0;
		let previewIndex = 0;

		// 处理返回的数据
		(res.Data || []).forEach((element: any) => {
			// 为普通图片列生成预览URL和索引
			imageHeaders.forEach((imageHeader) => {
				element[imageHeader.key + '__localurl__'] = '';
				if (element[imageHeader.key]) {
					// 生成缩略图URL，用于表格显示（提升质量到240x180）
					element[imageHeader.key + '__localurl__'] = `/api/_file/getfile/${element[imageHeader.key]}?width=240&height=180`;
					// 设置预览索引，用于图片预览组件
					element[imageHeader.key + '__preview__'] = imageIndex++;
					// 将原图URL添加到预览列表（用于高质量预览）
					const fullImageUrl = `/api/_file/getfile/${element[imageHeader.key]}`;
					state.picList.push(fullImageUrl);
				}
			});

			// 为base64图片列处理预览列表
			base64ImageHeaders.forEach((imageHeader) => {
				if (element[imageHeader.key]) {
					// 将base64图片添加到预览列表
					state.picList.push(element[imageHeader.key]);
				}
			});

			// 为图片列表类型处理URL和预览
			imageListHeaders.forEach((imageHeader) => {
				element[imageHeader.key + '__localurl__'] = [];
				element[imageHeader.key + '__preview__'] = [];

				if (element[imageHeader.key] && Array.isArray(element[imageHeader.key])) {
					element[imageHeader.key].forEach((imageItem: any, index: number) => {
						if (imageItem && imageItem.FileId) {
							// 生成缩略图URL，用于表格显示（提升质量到240x180）
							const thumbnailUrl = `/api/_file/getfile/${imageItem.FileId}?width=240&height=180`;
							element[imageHeader.key + '__localurl__'].push(thumbnailUrl);
							// 设置预览索引
							element[imageHeader.key + '__preview__'].push(imageIndex++);
							// 将原图URL添加到预览列表（用于点击预览）
							const fullImageUrl = `/api/_file/getfile/${imageItem.FileId}`;
							state.picList.push(fullImageUrl);
						} else {
							// 如果没有有效的FileId，添加空字符串保持索引一致
							element[imageHeader.key + '__localurl__'].push('');
							element[imageHeader.key + '__preview__'].push(-1);
						}
					});
				}
			});

			// 为文件预览类型处理URL和预览
			filePreviewHeaders.forEach((fileHeader) => {
				element[fileHeader.key + '__localurl__'] = [];
				element[fileHeader.key + '__preview__'] = [];

				if (element[fileHeader.key] && Array.isArray(element[fileHeader.key])) {
					element[fileHeader.key].forEach((fileItem: any, index: number) => {
						if (fileItem && fileItem.FileId) {
							// 为只有FileId的文件标记需要获取信息
							if (!fileItem.FileName && !fileItem.ContentType) {
								fileItem.__needsUpdate__ = true;
							}

							// 检查文件类型
							if (isImageFile(fileItem)) {
								// 图片文件：生成缩略图URL
								const thumbnailUrl = `/api/_file/getfile/${fileItem.FileId}?width=240&height=180`;
								element[fileHeader.key + '__localurl__'].push(thumbnailUrl);
								// 设置预览索引
								element[fileHeader.key + '__preview__'].push(previewIndex++);
								// 将原图URL添加到预览列表（用于el-image的预览）
								const fullImageUrl = `/api/_file/getfile/${fileItem.FileId}`;
								state.previewList.push(fullImageUrl);
							} else {
								// 非图片文件或未知类型：添加空URL，但记录预览索引
								element[fileHeader.key + '__localurl__'].push('');
								element[fileHeader.key + '__preview__'].push(previewIndex++);
								// 对于PDF等文件，也添加到预览列表以保持索引一致性
								const fileUrl = `/api/_file/getfile/${fileItem.FileId}`;
								state.previewList.push(fileUrl);
							}
						} else {
							// 如果没有有效的FileId，添加空字符串保持索引一致
							element[fileHeader.key + '__localurl__'].push('');
							element[fileHeader.key + '__preview__'].push(-1);
						}
					});
				}
			});

			datatemp.push(element);
		});

		// 根据是否为树形数据采用不同的处理方式
		if (isTreeState !== true) {
			// 平铺数据：直接赋值
			state.data = datatemp;
			localConfig.value.total = res.Count || 0;
		} else {
			// 树形数据：构建父子关系
			datatemp.forEach((element) => {
				element['children'] = datatemp.filter((x) => x[parentKey] == element.ID);
			});
			// 只显示顶级节点
			state.data = datatemp.filter((x) => !x[parentKey] || x[parentKey] == '');
			// 树形数据不显示总数
			localConfig.value.total = 0;
		}
	} catch (error) {
		// Table search failed
		ElMessage.error('数据加载失败');
	} finally {
		// 无论成功失败都要隐藏加载状态
		localConfig.value.loading = false;
	}
};

/**
 * 直接设置表格数据
 * 用于不需要API调用的场景，如导入数据、本地数据处理等
 * @param data - 要设置的数据数组
 * @param istree - 是否为树形数据
 * @param parentKey - 树形数据的父级ID字段名
 */
const setData = (data: any[], istree: boolean = false, parentKey: string = 'ParentId'): void => {
	try {
		if (istree !== true) {
			// 平铺数据处理
			if (props.config?.isSub) {
				listvalue.value = data;
			} else {
				state.data = data;
			}
			localConfig.value.total = data.length;
		} else {
			// 树形数据处理：构建父子关系
			data.forEach((element) => {
				element['children'] = data.filter((x) => x[parentKey] == element.ID);
			});

			// 设置顶级节点数据
			const topLevelData = data.filter((x) => !x[parentKey] || x[parentKey] == '');
			if (props.config?.isSub) {
				listvalue.value = topLevelData;
			} else {
				state.data = topLevelData;
			}
			localConfig.value.total = 0;
		}
		localConfig.value.loading = false;
	} catch (error) {
		// Set data failed
		ElMessage.error('数据设置失败');
	}
};

/**
 * 打印表格数据
 * 将表格数据转换为适合打印的格式并调用打印组件
 */
const doPrint = (): void => {
	try {
		// 将树形数据扁平化，并根据显示的列过滤数据
		const printData = other.flatTree(state.data, setHeader.value[0]?.key).map((item) => {
			const newItem: Record<string, any> = {};
			setHeader.value.forEach((header) => {
				// 处理空值显示
				newItem[header.key] = item[header.key] === undefined ? '' : item[header.key];
			});
			return newItem;
		});

		// 调用打印组件
		printJs({
			documentTitle: ' ',
			printable: printData,
			type: 'json',
			properties: setHeader.value.map((item) => ({
				field: item.key,
				displayName: item.title,
			})),
			gridHeaderStyle: `
				font-size:12px;
				border:0;
				border-top: 1px solid gray;
				border-left: 1px solid gray;
				border-right:1px solid gray;
				border-bottom:1px solid gray;
			`,
			gridStyle: `
				font-size:12px;
				border:0;
				border-top: 1px solid gray;
				border-left: 1px solid gray;
				border-right:1px solid gray;
				border-bottom:1px solid gray;
			`,
			style: `@page { size: landscape;} `,
		});
	} catch (error) {
		// Print failed
		ElMessage.error('打印失败');
	}
};

/**
 * 获取当前选中的行数据
 * @returns 选中的行数据数组
 */
const getSelectedRows = (): any[] => {
	return state.selectlist;
};

/**
 * =====================================================================================
 * 表格列拖拽排序功能 - 使用原生HTML5 Drag & Drop API
 * =====================================================================================
 *
 * 【功能概述】
 * 实现表格列的拖拽重新排序功能，用户可以通过鼠标拖拽改变列的显示顺序。
 * 使用原生HTML5 Drag & Drop API实现，避免第三方库的兼容性问题。
 *
 * 【技术实现】
 * 1. 🎯 原生API：使用HTML5 dragstart/dragover/drop事件
 * 2. 💾 状态同步：拖拽完成后同步更新Vue响应式状态
 * 3. 🔄 数据持久化：自动保存新的列顺序到localStorage
 * 4. ⚡ 性能优化：防止拖拽过程中的重复渲染
 */

// 拖拽状态变量
let dragStartIndex = -1;

/**
 * 拖拽开始处理
 */
const handleDragStart = (event: DragEvent, index: number): void => {
	dragStartIndex = index;
	if (event.dataTransfer) {
		event.dataTransfer.effectAllowed = 'move';
		event.dataTransfer.setData('text/html', `${index}`);
	}
	// 添加拖拽样式
	(event.target as HTMLElement)?.classList.add('dragging');
};

/**
 * 拖拽悬停处理
 */
const handleDragOver = (event: DragEvent): void => {
	event.preventDefault();
	if (event.dataTransfer) {
		event.dataTransfer.dropEffect = 'move';
	}
	// 添加悬停样式
	(event.currentTarget as HTMLElement)?.classList.add('drag-over');
};

/**
 * 拖拽放置处理
 */
const handleDrop = (event: DragEvent, dropIndex: number): void => {
	event.preventDefault();

	// 移除悬停样式
	(event.currentTarget as HTMLElement)?.classList.remove('drag-over');

	if (dragStartIndex === -1 || dragStartIndex === dropIndex) {
		return;
	}

	try {
		// 设置标志位，防止watch立即触发
		isDraggingSave = true;

		// 创建新的数组副本
		const newHeaders = [...localHeader.value];

		// 移动元素
		const draggedItem = newHeaders.splice(dragStartIndex, 1)[0];
		newHeaders.splice(dropIndex, 0, draggedItem);

		// 更新本地表头数组
		localHeader.value.splice(0, localHeader.value.length, ...newHeaders);

		// 保存拖拽后的列顺序到localStorage
		saveColumnOrder();

		// 显示成功提示 (可选)
		// ElMessage.success('列顺序已保存');
	} catch (error) {
		console.error('拖拽排序失败:', error);
		ElMessage.error('列排序失败，请重试');
		isDraggingSave = false;
		lastDragSaveTime = 0;
	}
};

/**
 * 拖拽结束处理
 */
const handleDragEnd = (event: DragEvent): void => {
	// 清理样式
	(event.target as HTMLElement)?.classList.remove('dragging');
	document.querySelectorAll('.tool-sortable-item.drag-over').forEach((el) => {
		el.classList.remove('drag-over');
	});

	// 重置拖拽状态
	dragStartIndex = -1;
};

/**
 * 表格设置面板显示处理
 * 现在只需要处理列设置的显示逻辑，不需要初始化拖拽库
 */

/**
 * 子表格删除行操作
 * @param index - 要删除的行索引
 */
const subDelete = (index: number): void => {
	try {
		listvalue.value.splice(index, 1);
	} catch (error) {
		// Delete failed
		ElMessage.error('删除失败');
	}
};

// ============ 图片处理通用函数 ============

/**
 * 生成图片URL的通用函数
 * 统一处理文件ID到缩略图URL的转换，支持自定义尺寸
 * @param fileId - 文件ID
 * @param width - 缩略图宽度，默认150
 * @param height - 缩略图高度，默认150
 * @returns 完整的图片URL
 */
const generateImageUrl = (fileId: string, width: number = 150, height: number = 150): string => {
	if (!fileId) return '';
	return `/api/_file/getfile/${fileId}?width=${width}&height=${height}`;
};

/**
 * 图片加载占位符的通用模板
 * 提供统一的加载中状态显示
 */
const getImagePlaceholderTemplate = () => `
	<div class="image-placeholder" style="background: #f0f0f0; display: flex; flex-direction: column; align-items: center; justify-content: center;">
		<i class="el-icon-loading" style="font-size: 20px; animation: rotate 2s linear infinite;"></i>
		<span style="font-size: 10px; margin-top: 4px;">加载中...</span>
	</div>
`;

/**
 * 图片错误状态的通用模板
 * 提供统一的加载失败状态显示
 */
const getImageErrorTemplate = () => `
	<div class="image-error">
		<i class="el-icon-picture-outline"></i>
		<span>加载失败</span>
	</div>
`;

/**
 * 获取统一的图片样式
 * @param item - 列配置
 * @returns 样式对象
 */
const getImageStyle = (item: TableColumn) => ({
	width: item.imageWidth ? item.imageWidth + 'px' : '80px',
	height: item.imageHeight ? item.imageHeight + 'px' : '60px',
	cursor: 'pointer',
});

/**
 * 获取要显示的图片列表
 * @param imageList - 图片数组
 * @param count - 显示数量
 */
const getDisplayImages = (imageList: any[], count: number): any[] => {
	if (!Array.isArray(imageList)) return [];
	return imageList.slice(0, count);
};

/**
 * 获取要显示的文件列表（图片优先）
 * @param fileList - 文件数组
 * @param count - 显示数量
 */
const getDisplayFiles = (fileList: any[], count: number): any[] => {
	if (!Array.isArray(fileList)) return [];

	// 将文件分为图片和非图片两类
	const imageFiles: any[] = [];
	const otherFiles: any[] = [];

	fileList.forEach((file) => {
		if (isImageFile(file)) {
			imageFiles.push(file);
		} else {
			otherFiles.push(file);
		}
	});

	// 图片优先，然后是其他文件
	const sortedFiles = [...imageFiles, ...otherFiles];

	return sortedFiles.slice(0, count);
};

/**
 * 检查文件是否为图片类型
 * @param fileItem - 文件对象
 */
const isImageFile = (fileItem: any): boolean => {
	if (!fileItem) return false;

	// 检查文件名扩展名
	if (fileItem.FileName || fileItem.Name) {
		const fileName = fileItem.FileName || fileItem.Name;
		const ext = fileName.toLowerCase().split('.').pop();
		return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext || '');
	}

	// 检查MIME类型
	if (fileItem.ContentType) {
		return fileItem.ContentType.startsWith('image/');
	}

	return false;
};

/**
 * 检查文件是否为PDF类型
 * @param fileItem - 文件对象
 */
const isPdfFile = (fileItem: any): boolean => {
	if (!fileItem) return false;

	// 检查文件名扩展名
	if (fileItem.FileName || fileItem.Name) {
		const fileName = fileItem.FileName || fileItem.Name;
		const ext = fileName.toLowerCase().split('.').pop();
		return ext === 'pdf';
	}

	// 检查MIME类型
	if (fileItem.ContentType) {
		return fileItem.ContentType === 'application/pdf';
	}

	return false;
};

/**
 * 获取文件图标类名
 * @param fileItem - 文件对象
 */
const getFileIconClass = (fileItem: any): string => {
	if (isImageFile(fileItem)) {
		return 'fa-file-image-o';
	} else if (isPdfFile(fileItem)) {
		return 'fa-file-pdf-o';
	} else {
		// 根据文件扩展名判断其他类型
		const fileName = fileItem.FileName || fileItem.Name || '';
		const ext = fileName.toLowerCase().split('.').pop() || '';

		const iconMap: Record<string, string> = {
			// 文档类型
			doc: 'fa-file-word-o',
			docx: 'fa-file-word-o',
			xls: 'fa-file-excel-o',
			xlsx: 'fa-file-excel-o',
			ppt: 'fa-file-powerpoint-o',
			pptx: 'fa-file-powerpoint-o',
			txt: 'fa-file-text-o',
			// 压缩文件
			zip: 'fa-file-archive-o',
			rar: 'fa-file-archive-o',
			'7z': 'fa-file-archive-o',
			// 音视频
			mp3: 'fa-file-audio-o',
			mp4: 'fa-file-video-o',
			avi: 'fa-file-video-o',
			// 代码文件
			js: 'fa-file-code-o',
			css: 'fa-file-code-o',
			html: 'fa-file-code-o',
			json: 'fa-file-code-o',
		};

		return iconMap[ext] || 'fa-file-o';
	}
};

/**
 * 获取文件类型文本
 * @param fileItem - 文件对象
 */
const getFileTypeText = (fileItem: any): string => {
	if (isImageFile(fileItem)) {
		return '图片文件';
	} else if (isPdfFile(fileItem)) {
		return 'PDF文档';
	} else {
		// 根据文件扩展名判断其他类型
		const fileName = fileItem.FileName || fileItem.Name || '';
		const ext = fileName.toLowerCase().split('.').pop() || '';

		const typeMap: Record<string, string> = {
			// 文档类型
			doc: 'Word文档',
			docx: 'Word文档',
			xls: 'Excel表格',
			xlsx: 'Excel表格',
			ppt: 'PPT演示',
			pptx: 'PPT演示',
			txt: '文本文档',
			// 压缩文件
			zip: '压缩文件',
			rar: '压缩文件',
			'7z': '压缩文件',
			// 音视频
			mp3: '音频文件',
			mp4: '视频文件',
			avi: '视频文件',
			// 代码文件
			js: 'JavaScript',
			css: '样式表',
			html: 'HTML文档',
			json: 'JSON数据',
		};

		return typeMap[ext] || '未知类型';
	}
};

/**
 * 获取文件预览样式
 * @param item - 列配置
 */
const getFilePreviewStyle = (item: TableColumn) => ({
	width: item.imageWidth ? item.imageWidth + 'px' : '80px',
	height: item.imageHeight ? item.imageHeight + 'px' : '60px',
	cursor: 'pointer',
});

/**
 * 获取文件预览索引
 * @param row - 数据行
 * @param key - 字段key
 * @param index - 索引
 */
const getFilePreviewIndex = (row: any, key: string, index: number): number => {
	const previewKey = `${key}__preview__`;
	if (row[previewKey] && Array.isArray(row[previewKey]) && typeof row[previewKey][index] === 'number') {
		return row[previewKey][index];
	}
	return index;
};

/**
 * 获取imageList中单个图片的URL - 参考image类型的实现
 * @param imageItem - 图片项对象
 * @param row - 数据行
 * @param key - 字段key
 * @param index - 索引
 */
const getImageListUrl = (imageItem: any, row: any, key: string, index: number): string => {
	// 参考image类型：优先使用处理过的__localurl__字段
	const localUrlKey = `${key}__localurl__`;
	if (row[localUrlKey] && Array.isArray(row[localUrlKey]) && row[localUrlKey][index]) {
		return row[localUrlKey][index];
	}

	// 如果没有预处理的URL，尝试直接使用FileId生成缩略图URL
	if (imageItem && typeof imageItem === 'object' && imageItem.FileId) {
		return `/api/_file/getfile/${imageItem.FileId}`;
	}

	return '';
};

/**
 * 获取imageList中单个图片的预览索引 - 参考image类型的实现
 * @param row - 数据行
 * @param key - 字段key
 * @param index - 索引
 */
const getImageListPreviewIndex = (row: any, key: string, index: number): number => {
	// 参考image类型：优先使用处理过的__preview__字段
	const previewKey = `${key}__preview__`;
	if (row[previewKey] && Array.isArray(row[previewKey]) && typeof row[previewKey][index] === 'number') {
		return row[previewKey][index];
	}

	// 如果没有预处理的索引，尝试使用Order字段
	const imageList = row[key];
	if (Array.isArray(imageList) && imageList[index] && typeof imageList[index].Order === 'number') {
		return imageList[index].Order;
	}

	return index;
};

/**
 * 预览所有图片（点击"更多"时）
 * @param imageList - 图片数组
 * @param startIndex - 开始索引
 */
const previewAllImages = (imageList: any[], startIndex: number): void => {
	// 可以在这里添加特殊的预览逻辑，目前依赖图片的preview-src-list
	if (Array.isArray(imageList) && imageList.length > 0) {
	}
};

/**
 * 根据文件ID获取文件信息
 * @param fileId - 文件ID
 */
const loadFileInfo = async (fileId: string): Promise<{ fileName: string; fileType: string } | null> => {
	try {
		// 动态导入文件API
		const fileApi = (await import('/@/api/file/index')).default;
		const api = fileApi();

		// 获取文件名
		const fileName = await api.getName(fileId);
		if (!fileName || typeof fileName !== 'string') {
			return null;
		}

		// 根据文件名推断文件类型
		const ext = fileName.toLowerCase().split('.').pop() || '';
		let fileType = 'other';

		if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)) {
			fileType = 'image';
		} else if (ext === 'pdf') {
			fileType = 'pdf';
		}

		return { fileName, fileType };
	} catch (error) {
		console.warn('获取文件信息失败:', fileId, error);
		return null;
	}
};

/**
 * 更新文件对象信息
 * @param fileItem - 文件对象
 */
const updateFileItemInfo = async (fileItem: any): Promise<void> => {
	if (!fileItem || !fileItem.FileId || fileItem.FileName) {
		return; // 如果没有FileId或已有文件名，跳过
	}

	const fileInfo = await loadFileInfo(fileItem.FileId);
	if (fileInfo) {
		fileItem.FileName = fileInfo.fileName;
		fileItem.ContentType =
			fileInfo.fileType === 'image' ? 'image/jpeg' : fileInfo.fileType === 'pdf' ? 'application/pdf' : 'application/octet-stream';
	}
};

/**
 * 按文件类型排序（图片优先）
 * @param fileList - 文件数组
 */
const getSortedFilesByType = (fileList: any[]): any[] => {
	if (!Array.isArray(fileList)) return [];

	// 将文件分为图片和非图片两类
	const imageFiles: any[] = [];
	const otherFiles: any[] = [];

	fileList.forEach((file) => {
		if (isImageFile(file)) {
			imageFiles.push(file);
		} else {
			otherFiles.push(file);
		}
	});

	// 图片优先，然后是其他文件
	return [...imageFiles, ...otherFiles];
};

/**
 * 打开文件预览对话框
 * @param fileList - 文件数组
 * @param startIndex - 开始索引
 */
const openFilePreview = async (fileList: any[], startIndex: number = 0): Promise<void> => {
	if (!Array.isArray(fileList) || fileList.length === 0) return;

	try {
		// 将文件按图片优先排序
		const sortedFiles = getSortedFilesByType(fileList);

		// 先显示预览窗口和loading状态
		filePreviewVisible.value = true;
		isLoadingPreview.value = true;
		currentPreviewFiles.value = sortedFiles;
		currentPreviewIndex.value = startIndex;
		pdfLoadError.value = false;

		// 为只有FileId的文件获取详细信息
		const updatePromises = sortedFiles.map((fileItem) => updateFileItemInfo(fileItem));
		await Promise.all(updatePromises);

		// 更新文件信息后重新设置
		currentPreviewFiles.value = [...sortedFiles]; // 触发响应式更新
	} catch (error) {
		console.error('打开文件预览失败:', error);
		ElMessage.error('文件预览加载失败');
		filePreviewVisible.value = false; // 出错时关闭预览
	} finally {
		isLoadingPreview.value = false;
	}
};

/**
 * 关闭文件预览对话框
 */
const closeFilePreview = (): void => {
	filePreviewVisible.value = false;
	currentPreviewFiles.value = [];
	currentPreviewIndex.value = 0;
	pdfLoadError.value = false;
	isLoadingPreview.value = false;
};

/**
 * 切换到上一个文件
 */
const prevFile = (): void => {
	if (currentPreviewIndex.value > 0) {
		currentPreviewIndex.value--;
		pdfLoadError.value = false;
	}
};

/**
 * 切换到下一个文件
 */
const nextFile = (): void => {
	if (currentPreviewIndex.value < currentPreviewFiles.value.length - 1) {
		currentPreviewIndex.value++;
		pdfLoadError.value = false;
	}
};

/**
 * PDF加载成功
 */
const onPdfLoad = (): void => {
	pdfLoadError.value = false;
};

/**
 * PDF加载失败
 */
const onPdfError = (event: Event): void => {
	console.warn('PDF加载失败:', event);
	pdfLoadError.value = true;
};

/**
 * 获取当前预览文件
 */
const currentPreviewFile = computed(() => {
	if (currentPreviewFiles.value.length === 0) return null;
	return currentPreviewFiles.value[currentPreviewIndex.value];
});

/**
 * 获取图片预览URL
 * @param fileItem - 文件对象
 */
const getImagePreviewUrl = (fileItem: any): string => {
	if (!fileItem || !fileItem.FileId) return '';
	return `/api/_file/getfile/${fileItem.FileId}`;
};

/**
 * 获取PDF预览URL
 * @param fileItem - 文件对象
 */
const getPdfPreviewUrl = (fileItem: any): string => {
	if (!fileItem || !fileItem.FileId) return '';
	return `/api/_file/getfile/${fileItem.FileId}`;
};

/**
 * 文件下载处理
 * @param data - 文件数据或文件ID
 */
const download = (data: any): void => {
	try {
		fileapi().downloadFile(data);
	} catch (error) {
		// Download failed
		ElMessage.error('下载失败');
	}
};

/**
 * 文件预览下载处理器
 * @param file - 文件对象
 */
const handleFileDownload = (file: any): void => {
	try {
		const fileId = file?.FileId || file?.Id;
		if (fileId) {
			download(fileId);
		} else {
			ElMessage.error('文件ID不存在');
		}
	} catch (error) {
		ElMessage.error('下载失败');
	}
};

/**
 * 子表格添加新行
 */
const subCreate = (): void => {
	try {
		listvalue.value.push({});
	} catch (error) {
		// Create failed
		ElMessage.error('添加失败');
	}
};

/**
 * 切换表格密度
 * 循环切换：默认 -> 紧凑 -> 舒适 -> 默认
 */
const toggleTableDensity = (): void => {
	if (tableSize.value === 'default') {
		tableSize.value = 'small';
	} else if (tableSize.value === 'small') {
		tableSize.value = 'large';
	} else {
		tableSize.value = 'default';
	}
};

/**
 * 重置所有列宽到默认值
 * 清除用户自定义的列宽设置
 */
const resetColumnWidths = (): void => {
	try {
		// 清除所有列的用户自定义宽度
		localHeader.value.forEach((column) => {
			column.userWidth = undefined;
		});

		// 清除localStorage中的列宽设置
		const settings = getCurrentTableSettings();
		if (settings) {
			delete settings.columnWidths;
			const allSettings = getAllTableSettings();
			allSettings[getTableKey()] = settings;
			localStorage.setItem(TABLE_SETTINGS, JSON.stringify(allSettings));
		}

		ElMessage.success('列宽已重置为默认值');
	} catch (error) {
		console.error('重置列宽失败:', error);
		ElMessage.error('重置列宽失败');
	}
};

// ============ 统计功能相关 ============

/**
 * 获取统计方法
 * Element Plus表格的summary-method属性回调函数
 */
const getSummaryMethod = ({ columns, data }: { columns: any[]; data: any[] }) => {
	const sums: string[] = [];

	columns.forEach((column, index) => {
		if (index === 0) {
			// 第一列显示统计标题
			sums[index] = localConfig.value.summaryText || '合计';
			return;
		}

		// 查找对应的列配置
		const headerColumn = localHeader.value.find((h) => h.key === column.property);

		// 如果有后端计算的数据，优先使用
		if (state.summaryData[column.property]) {
			sums[index] = state.summaryData[column.property];
			return;
		}

		// 如果有配置统计
		if (headerColumn?.summary) {
			const summary = headerColumn.summary;
			const values = data.map((item) => item[column.property]);

			if (summary.custom) {
				// 自定义统计函数
				sums[index] = summary.custom(values);
			} else if (summary.sum) {
				// 计算合计
				const numericValues = values
					.filter((val) => val !== null && val !== undefined && val !== '' && !isNaN(Number(val)))
					.map((val) => Number(val));
				if (numericValues.length > 0) {
					const sum = numericValues.reduce((prev, curr) => prev + curr, 0);
					sums[index] = sum.toFixed(2);
				} else {
					sums[index] = '';
				}
			} else if (summary.avg) {
				// 计算平均值
				const numericValues = values
					.filter((val) => val !== null && val !== undefined && val !== '' && !isNaN(Number(val)))
					.map((val) => Number(val));
				if (numericValues.length > 0) {
					const avg = numericValues.reduce((prev, curr) => prev + curr, 0) / numericValues.length;
					sums[index] = avg.toFixed(2);
				} else {
					sums[index] = '';
				}
			} else if (summary.max) {
				// 计算最大值
				const numericValues = values
					.filter((val) => val !== null && val !== undefined && val !== '' && !isNaN(Number(val)))
					.map((val) => Number(val));
				if (numericValues.length > 0) {
					sums[index] = Math.max(...numericValues).toFixed(2);
				} else {
					sums[index] = '';
				}
			} else if (summary.min) {
				// 计算最小值
				const numericValues = values
					.filter((val) => val !== null && val !== undefined && val !== '' && !isNaN(Number(val)))
					.map((val) => Number(val));
				if (numericValues.length > 0) {
					sums[index] = Math.min(...numericValues).toFixed(2);
				} else {
					sums[index] = '';
				}
			} else if (summary.count) {
				// 计算计数
				sums[index] = values.length.toString();
			} else {
				sums[index] = '';
			}
		} else {
			// 没有配置统计，显示空
			sums[index] = '';
		}
	});

	return sums;
};

/**
 * 单元格合并方法
 * 支持根据指定字段自动合并相同值的行
 */
const spanMethod = ({
	row,
	column,
	rowIndex,
	columnIndex,
}: {
	row: any;
	column: any;
	rowIndex: number;
	columnIndex: number;
}): [number, number] | void => {
	// 如果有自定义的合并方法，优先使用
	if (localConfig.value.spanMethod) {
		return localConfig.value.spanMethod({ row, column, rowIndex, columnIndex });
	}

	// 如果没有配置合并字段，不进行合并
	if (!localConfig.value.mergeFields || localConfig.value.mergeFields.length === 0) {
		return;
	}

	const data = props.config?.isSub === true ? listvalue.value : state.data;
	const property = column.property;

	// 如果当前列不在合并字段列表中，不进行合并
	if (!localConfig.value.mergeFields.includes(property)) {
		return;
	}

	let rowspan = 1;
	let colspan = 1;

	// 计算向下合并的行数
	for (let i = rowIndex + 1; i < data.length; i++) {
		// 检查所有合并字段是否都相同
		const shouldMerge = localConfig.value.mergeFields.every((field) => data[rowIndex][field] === data[i][field]);

		if (shouldMerge) {
			rowspan++;
		} else {
			break;
		}
	}

	// 检查是否是合并组的第一行
	if (rowIndex > 0) {
		const shouldMergeWithPrevious = localConfig.value.mergeFields.every((field) => data[rowIndex][field] === data[rowIndex - 1][field]);

		if (shouldMergeWithPrevious) {
			// 不是第一行，返回 [0, 0] 隐藏单元格
			return [0, 0];
		}
	}

	return [rowspan, colspan];
};

/**
 * 调用后端接口计算合计数据
 */
const doCalculate = async (): Promise<void> => {
	try {
		state.calculating = true;

		if (localConfig.value.calculateApi) {
			// 如果配置了后端接口，调用后端计算
			const requestData = {
				...state.searcher,
				// 可以添加其他需要的参数，比如当前筛选条件等
			};

			// const response = await other.post(localConfig.value.calculateApi, requestData);
			const response = {
				Data: {
					score: 100,
				},
			};
			if (response && response.Data) {
				// 更新统计数据
				state.summaryData = response.Data;
				ElMessage.success('合计数据计算完成');
			} else {
				ElMessage.warning('未获取到合计数据');
			}
		} else {
			// 如果没有配置后端接口，使用前端计算
			// 清空后端数据，让前端自动计算生效
			state.summaryData = {};
			ElMessage.success('合计数据已更新');
		}
	} catch (error) {
		console.error('计算合计数据失败:', error);
		ElMessage.error('计算合计数据失败');
	} finally {
		state.calculating = false;
	}
};

// ============ 标签相关函数 ============

/**
 * 获取标签类型（颜色主题）
 * 支持固定值和动态函数两种方式
 * @param textOrValue - 显示文本或原始值
 * @param column - 列配置
 * @param row - 行数据
 * @param value - 原始值
 */
const getTagType = (textOrValue: any, column?: TableColumn, row?: any, value?: any) => {
	const validTypes = ['primary', 'success', 'info', 'warning', 'danger'];

	// 如果有自定义的tagType函数，调用函数
	if (column?.tagType && typeof column.tagType === 'function') {
		const result = column.tagType(row, value);
		// 确保返回值是有效的类型，如果不是则使用默认值
		return validTypes.includes(result) ? result : 'info';
	}

	// 如果有固定的tagType，直接返回
	if (column?.tagType && typeof column.tagType === 'string') {
		// 确保返回值是有效的类型，如果不是则使用默认值
		return validTypes.includes(column.tagType) ? column.tagType : 'info';
	}

	// 默认为info类型
	return 'info';
};

/**
 * 获取标签自定义颜色
 * 支持固定值和动态函数两种方式
 * @param value - 原始值
 * @param column - 列配置
 * @param row - 行数据
 */
const getTagColor = (value: any, column?: TableColumn, row?: any): string | undefined => {
	// 如果有自定义颜色函数，调用函数
	if (column?.tagColor && typeof column.tagColor === 'function') {
		return column.tagColor(row, value);
	}

	// 如果有固定的颜色，返回固定颜色
	if (column?.tagColor && typeof column.tagColor === 'string') {
		return column.tagColor;
	}

	// 默认不设置自定义颜色，使用type对应的颜色
	return undefined;
};

// 监听表格密度变化并保存到localStorage
watch(tableSize, (newSize) => {
	localStorage.setItem('table-density', newSize);
});

// 暴露组件方法给父组件使用
defineExpose({
	/** 执行搜索操作 */
	doSearch,
	/** 获取选中的行数据 */
	getSelectedRows,
	/** 直接设置表格数据 */
	setData,
	/** 清除选择状态 */
	clearSelection,
	/** 切换表格密度 */
	toggleTableDensity,
	inheritAttrs: false,
});
</script>

<style scoped lang="scss">
// 全局斑马纹样式 - 最高优先级
:deep(.el-table__body-wrapper .el-table__body tr.el-table__row--striped) {
	background-color: var(--el-fill-color-light) !important;
}

:deep(.el-table__body-wrapper .el-table__body tr.el-table__row--striped td) {
	background-color: var(--el-fill-color-light) !important;
}

:deep(.el-table__body-wrapper .el-table__body tr.el-table__row--striped td .el-table__cell) {
	background-color: var(--el-fill-color-light) !important;
}

.table-container {
	flex: 1;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	background: var(--el-bg-color);
	border-radius: 6px;
	box-shadow: var(--el-box-shadow-light);
	border: 1px solid var(--el-border-color);
	margin: 5px 0;
	padding: 10px;

	.el-table {
		flex: 1;
		border-radius: 6px;
		overflow: hidden;

		// 固定操作栏 - 使用CSS选择器自动识别操作列，无需JavaScript
		:deep(.el-table__header-wrapper) {
			// 通过class-name="operation-column"识别操作列
			th.operation-column {
				position: sticky !important;
				right: 0 !important;
				z-index: 10 !important;
				background-color: var(--el-fill-color-blank) !important;
				box-shadow: -1px 0 4px var(--el-box-shadow-light) !important;

				&:hover {
					background-color: var(--el-fill-color-light) !important;
				}
			}

			// 兜底方案：最后一列作为操作列（当有超过8列时）
			th:last-child {
				@media (min-width: 768px) {
					position: sticky !important;
					right: 0 !important;
					z-index: 10 !important;
					background-color: var(--el-fill-color-blank) !important;
					box-shadow: -1px 0 4px var(--el-box-shadow-light) !important;

					&:hover {
						background-color: var(--el-fill-color-light) !important;
					}
				}
			}
		}

		:deep(.el-table__body-wrapper) {
			// 通过class-name="operation-column"识别操作列
			td.operation-column {
				position: sticky !important;
				right: 0 !important;
				z-index: 9 !important;
				background-color: var(--el-bg-color) !important;
				box-shadow: -1px 0 4px var(--el-box-shadow-light) !important;
			}

			tr.el-table__row--striped td.operation-column {
				background-color: var(--el-fill-color-light) !important;
			}

			tr:hover td.operation-column {
				background-color: var(--el-fill-color-light) !important;
			}

			// 兜底方案：最后一列作为操作列（当有超过8列时）
			td:last-child {
				@media (min-width: 768px) {
					position: sticky !important;
					right: 0 !important;
					z-index: 9 !important;
					background-color: var(--el-bg-color) !important;
					box-shadow: -1px 0 4px var(--el-box-shadow-light) !important;
				}
			}

			tr.el-table__row--striped td:last-child {
				@media (min-width: 768px) {
					background-color: var(--el-fill-color-light) !important;
				}
			}

			tr:hover td:last-child {
				@media (min-width: 768px) {
					background-color: var(--el-fill-color-light) !important;
				}
			}
		}

		// 表头样式优化
		:deep(.el-table__header-wrapper) {
			.el-table__header th {
				background-color: var(--el-fill-color-blank);
				border-bottom: 1px solid var(--el-border-color);

				.el-table__cell {
					color: var(--el-text-color-primary);
					font-weight: 500;
					padding: 16px 12px;
					border-right: 1px solid var(--el-border-color-lighter);

					&:last-child {
						border-right: none;
					}
				}

				// 列宽调整手柄样式优化
				&.is-resizing {
					.el-table__cell {
						background-color: var(--el-color-primary-light-9);
					}
				}

				// 调整手柄悬停效果
				&:hover .gutter {
					background-color: var(--el-color-primary);
					opacity: 0.8;
				}

				.gutter {
					background-color: var(--el-border-color);
					transition: all 0.2s ease;

					&:hover {
						background-color: var(--el-color-primary);
						opacity: 1;
					}
				}
			}
		}

		// 表体样式优化
		:deep(.el-table__body-wrapper) {
			// 树形表格展开图标和内容在同一行 - 只影响包含展开图标的单元格
			.el-table__expand-icon {
				display: inline-flex !important;
				vertical-align: middle !important;
				margin-right: 4px !important;
			}

			// 树形表格缩进容器
			.el-table__indent {
				display: inline-block !important;
				vertical-align: middle !important;
			}

			// 只针对包含展开图标的单元格（树形结构的第一列）防止换行
			.cell:has(.el-table__expand-icon),
			.cell:has(.el-table__indent) {
				white-space: nowrap !important;
				display: inline-flex !important;
				align-items: center !important;
				flex-wrap: nowrap !important;
			}

			// 单元格链接样式
			.table-cell-link {
				padding: 0;
				line-height: 1.2;
				color: var(--el-color-primary);
				font-weight: 500;
				max-width: 100%;
				vertical-align: middle;

				.cell-link-text {
					display: inline-block;
					max-width: 100%;
					overflow: hidden;
					text-overflow: ellipsis;
					white-space: nowrap;
				}

				&:hover,
				&:focus {
					color: var(--el-color-primary-dark-2);
				}

				&.is-disabled {
					color: var(--el-text-color-placeholder);
					pointer-events: none;
				}
			}
			.el-table__body tr {
				background-color: var(--el-bg-color);
				border-bottom: 1px solid var(--el-border-color-lighter);
				transition: background-color 0.2s ease;

				&.el-table__row--striped {
					background-color: #f0f2f5 !important;
				}

				&.el-table__row--striped td {
					background-color: var(--el-fill-color-light) !important;
				}

				&.el-table__row--striped td .el-table__cell {
					background-color: var(--el-fill-color-light) !important;
				}

				&:hover {
					background-color: var(--el-fill-color-light);
				}

				td {
					border-right: 1px solid var(--el-border-color-lighter);

					&:last-child {
						border-right: none;
					}

					.el-table__cell {
						color: var(--el-text-color-primary);
						padding: 14px 12px;
					}

					// 表格中的操作按钮样式 - 使用更高优先级覆盖WtmButton样式
					.operation-container .el-button,
					.el-button {
						display: inline-flex !important;
						align-items: center !important;
						gap: 2px !important;
						padding: 0 4px !important;
						margin: 0 2px !important;
						font-size: 13px !important;
						font-weight: 400 !important;
						cursor: pointer !important;
						user-select: none !important;
						color: #666 !important;
						background: none !important;
						border: none !important;
						box-shadow: none !important;
						transition: color 0.2s ease !important;
						text-decoration: none !important;
						white-space: nowrap !important;
						flex-shrink: 0 !important;
						min-height: auto !important;
						height: auto !important;
						line-height: 1.2 !important;

						// 悬停效果 - 只改变颜色
						&:hover {
							background: none !important;
							border: none !important;
							transform: none !important;
							box-shadow: none !important;
							color: var(--el-color-primary) !important;

							i {
								color: var(--el-color-primary) !important;
							}
						}

						&:active {
							transform: none !important;
							box-shadow: none !important;
						}

						// 所有类型按钮统一样式
						&.el-button--danger:hover,
						&.el-button--warning:hover,
						&.el-button--success:hover,
						&.el-button--primary:hover,
						&.el-button--info:hover {
							background: none !important;
							border: none !important;
							color: var(--el-color-primary) !important;
							transform: none !important;
							box-shadow: none !important;

							i {
								color: var(--el-color-primary) !important;
							}
						}

						// 禁用状态
						&:disabled,
						&.is-disabled {
							opacity: 0.5 !important;
							cursor: not-allowed !important;
							transform: none !important;
							box-shadow: none !important;

							&:hover {
								transform: none !important;
								background: none !important;
								color: #666 !important;
							}
						}

						// 文本按钮特殊处理
						&.is-text {
							background: none !important;
							border: none !important;
							box-shadow: none !important;

							&:hover {
								background: none !important;
								border: none !important;
								transform: none !important;
								box-shadow: none !important;
								color: #1890ff !important;
							}
						}

						// 审批按钮特殊样式
						&.el-button--primary.is-text {
							color: #409eff !important;
							font-weight: bold !important;

							&:hover {
								color: #337ecc !important;
							}

							i {
								color: #409eff !important;
							}

							&:hover i {
								color: #337ecc !important;
							}

							// 暗黑模式适配
							@media (prefers-color-scheme: dark) {
								color: #79bbff !important;

								&:hover {
									color: #a0cfff !important;
								}

								i {
									color: #79bbff !important;
								}

								&:hover i {
									color: #a0cfff !important;
								}
							}
						}

						// 图标样式
						i {
							font-size: 12px !important;
							transition: color 0.2s ease !important;
						}

						// 强制覆盖WtmButton的所有可能样式
						&.wtm-button,
						&[class*='wtm-'],
						&[class*='el-button'] {
							padding: 0 4px !important;
							margin: 0 2px !important;
							font-size: 13px !important;
							background: none !important;
							border: none !important;
							box-shadow: none !important;
							min-width: auto !important;
							min-height: auto !important;
							height: auto !important;
						}
					}
				}
			}
		}

		// 空状态
		:deep(.el-table__empty-block) {
			background-color: var(--el-bg-color);

			.el-table__empty-text {
				color: var(--el-text-color-secondary);
			}
		}

		// 表格行过渡效果流畅
		:deep(.el-table__body) tr,
		:deep(.el-table__body-wrapper) tr {
			transition: background-color 0.2s ease-out;
		}

		// 统计行样式 - 简约明显设计
		:deep(.el-table__footer-wrapper) {
			.el-table__footer {
				background-color: #fafbfc;

				tr {
					background-color: #fafbfc !important;

					td {
						border-top: 2px solid var(--el-color-primary);
						border-right: 1px solid var(--el-border-color-lighter);
						font-weight: bold !important;

						&:last-child {
							border-right: none;
						}

						.el-table__cell {
							color: var(--el-text-color-primary) !important;
							font-weight: bold !important;
							font-size: 14px;
							padding: 16px 12px;
							background-color: transparent;

							div {
								font-weight: bold !important;
							}

							// 合计标题样式
							&:has(> div:first-child) {
								div:first-child {
									color: var(--el-color-primary) !important;
									font-weight: bold !important;
									font-size: 15px;
								}
							}
						}
					}
				}
			}
		}
	}

	// 图片样式优化
	.table-image-container {
		display: flex;
		justify-content: center;
		align-items: center;
		padding: 4px;

		.table-image {
			border-radius: 8px;
			border: 2px solid #e4e7ed;
			box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
			transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
			cursor: pointer;
			overflow: hidden;
			object-fit: cover;
			position: relative;

			// 添加预览提示
			&::after {
				content: '点击预览';
				position: absolute;
				bottom: 0;
				left: 0;
				right: 0;
				background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
				color: white;
				font-size: 11px;
				text-align: center;
				padding: 4px;
				opacity: 0;
				transition: opacity 0.3s ease;
				pointer-events: none;
			}

			&:hover {
				border-color: #409eff;
				box-shadow: 0 6px 20px rgba(64, 158, 255, 0.25);
				transform: scale(1.08) translateY(-2px);

				&::after {
					opacity: 1;
				}
			}

			:deep(.el-image__inner) {
				border-radius: 6px;
				transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
			}

			// 图片加载状态优化
			:deep(.el-image__placeholder) {
				background: linear-gradient(90deg, #f0f2f5 25%, #e6f4ff 50%, #f0f2f5 75%);
				background-size: 200% 100%;
				animation: shimmer 1.5s infinite;
				display: flex;
				align-items: center;
				justify-content: center;
				color: #999;
				font-size: 12px;
			}

			:deep(.el-image__error) {
				background: #fafafa;
				border: 1px dashed #d9d9d9;
				display: flex;
				align-items: center;
				justify-content: center;
				color: #999;
				font-size: 12px;
			}

			&:hover :deep(.el-image__inner) {
				filter: brightness(1.1) contrast(1.05);
			}
		}

		.image-placeholder,
		.image-error {
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			width: 100%;
			height: 100%;
			background-color: #f5f7fa;
			color: #909399;
			border-radius: 6px;

			i {
				font-size: 24px;
				margin-bottom: 4px;
			}

			span {
				font-size: 12px;
			}
		}

		.image-error {
			background-color: #fef0f0;
			color: #f56c6c;
		}
	}

	// 标签样式优化
	.empty-tag {
		color: var(--el-text-color-placeholder);
		font-style: italic;
	}

	:deep(.el-tag) {
		margin: 2px 0;

		&.el-tag--success {
			background-color: #f0f9ff;
			color: #67c23a;
			border-color: #b3e19d;
		}

		&.el-tag--info {
			background-color: #f4f4f5;
			color: #909399;
			border-color: #d3d4d6;
		}

		&.el-tag--warning {
			background-color: #fdf6ec;
			color: #e6a23c;
			border-color: #f5dab1;
		}

		&.el-tag--danger {
			background-color: #fef0f0;
			color: #f56c6c;
			border-color: #fbc4c4;
		}

		&.el-tag--primary {
			background-color: #ecf5ff;
			color: #409eff;
			border-color: #b3d8ff;
		}
	}

	.table-footer {
		display: flex;
		justify-content: space-between;
		align-items: center;
		background: var(--el-bg-color);
		margin: 5px 0;

		.el-pagination {
			background: transparent;

			:deep(.el-pagination__total) {
				color: var(--el-text-color-regular);
			}

			:deep(.el-pagination__sizes) {
				.el-select {
					.el-select__wrapper {
						background-color: var(--el-fill-color-blank);
						border-color: var(--el-border-color);

						&:hover {
							border-color: var(--el-border-color-hover);
						}
					}
				}
			}

			:deep(.btn-prev),
			:deep(.btn-next) {
				background-color: var(--el-fill-color-blank);
				border-color: var(--el-border-color);
				color: var(--el-text-color-regular);

				&:hover {
					background-color: var(--el-color-primary);
					border-color: var(--el-color-primary);
					color: var(--el-color-white);
				}

				&.is-disabled {
					background-color: var(--el-fill-color-light);
					border-color: var(--el-border-color-light);
					color: var(--el-text-color-disabled);
				}
			}

			:deep(.el-pager) {
				li {
					background-color: var(--el-fill-color-blank);
					border-color: var(--el-border-color);
					color: var(--el-text-color-regular);

					&:hover {
						background-color: var(--el-color-primary-light-9);
						border-color: var(--el-color-primary-light-7);
						color: var(--el-color-primary);
					}

					&.is-active {
						background-color: var(--el-color-primary);
						border-color: var(--el-color-primary);
						color: var(--el-color-white);
					}
				}
			}

			:deep(.el-pagination__jump) {
				color: var(--el-text-color-regular);

				.el-input {
					.el-input__wrapper {
						background-color: var(--el-fill-color-blank);
						border-color: var(--el-border-color);

						&:hover {
							border-color: var(--el-border-color-hover);
						}

						&.is-focus {
							border-color: var(--el-color-primary);
						}

						.el-input__inner {
							color: var(--el-text-color-primary);
						}
					}
				}
			}
		}

		.table-footer-tool {
			display: flex;
			align-items: center;
			gap: 8px;

			.table-tool-btn {
				display: flex;
				align-items: center;
				gap: 6px;
				padding: 8px 12px;
				font-size: 13px;
				font-weight: 400;
				border-radius: 6px;
				transition: all 0.2s ease;
				cursor: pointer;
				user-select: none;
				color: var(--el-text-color-primary);
				background: var(--el-fill-color-blank);
				border: 1px solid var(--el-border-color);
				box-shadow: var(--el-box-shadow-light);

				i {
					font-size: 14px;
					color: var(--el-text-color-regular);
					transition: color 0.2s ease;
				}

				span {
					font-size: 13px;
					color: var(--el-text-color-primary);
					transition: color 0.2s ease;
				}

				&:hover {
					background: var(--el-color-primary-light-9);
					border-color: var(--el-color-primary-light-7);
					transform: translateY(-1px);
					box-shadow: var(--el-box-shadow);

					i,
					span {
						color: var(--el-color-primary);
					}
				}

				&:active {
					transform: translateY(0);
				}

				// 设置按钮特殊样式
				&:has(i.fa-gear) {
					background: linear-gradient(135deg, var(--el-color-warning-light-9) 0%, var(--el-color-warning-light-8) 100%);
					border-color: var(--el-color-warning-light-7);

					i,
					span {
						color: var(--el-color-warning);
					}

					&:hover {
						background: linear-gradient(135deg, var(--el-color-warning-light-8) 0%, var(--el-color-warning-light-7) 100%);
						border-color: var(--el-color-warning-light-5);

						i,
						span {
							color: var(--el-color-warning-dark-2);
						}
					}
				}

				// 合计按钮特殊样式
				&:has(i.fa-plus-circle) {
					background: linear-gradient(135deg, var(--el-color-success-light-9) 0%, var(--el-color-success-light-8) 100%);
					border-color: var(--el-color-success-light-7);

					i,
					span {
						color: var(--el-color-success);
					}

					&:hover {
						background: linear-gradient(135deg, var(--el-color-success-light-8) 0%, var(--el-color-success-light-7) 100%);
						border-color: var(--el-color-success-light-5);

						i,
						span {
							color: var(--el-color-success-dark-2);
						}
					}
				}

				// 计算按钮加载状态
				&.loading {
					opacity: 0.7;
					cursor: not-allowed;

					&:hover {
						background: var(--el-fill-color-blank);
						border-color: var(--el-border-color);
						transform: none;

						i,
						span {
							color: var(--el-text-color-regular);
						}
					}
				}
			}
		}
	}

	// 响应式优化
	@media (max-width: 768px) {
		padding: 12px;
		border-radius: 4px;
		margin: 12px 0;

		.el-table {
			border-radius: 4px;

			&.table-compact :deep(.el-table__header-wrapper) {
				.el-table__header th .el-table__cell {
					padding: 8px 6px;
					font-size: 12px;
				}
			}

			&.table-compact :deep(.el-table__body-wrapper) {
				.el-table__body tr td {
					padding: 6px;

					.el-table__cell {
						font-size: 12px;
					}
				}
			}
		}

		.table-footer {
			padding: 12px 16px;
			flex-direction: column;
			gap: 12px;
			border-radius: 0 0 4px 4px;
			margin-top: 16px;
			margin-left: -12px;
			margin-right: -12px;
			margin-bottom: -12px;

			.table-footer-tool {
				justify-content: center;
				flex-wrap: wrap;

				.table-tool-btn {
					padding: 6px 10px;
					font-size: 13px;

					i,
					span {
						font-size: 13px;
					}
				}

				.el-popover__reference {
					.table-tool-btn {
						padding: 6px 10px;
						font-size: 13px;

						i,
						span {
							font-size: 13px;
						}
					}
				}
			}

			:deep(.el-pagination) {
				.el-pagination__sizes,
				.el-pagination__jump {
					display: none;
				}
			}
		}
	}

	// 悬停显示操作按钮功能 - 简化版本
	:deep(.operation-container) {
		opacity: 1;
		visibility: visible;
		transform: none;
		pointer-events: auto;
		transition: none;
		// ... 保留按钮样式部分
	}

	// ============ 操作列悬停效果优化 ============

	// 操作列标题默认透明，悬停时显示
	:deep(.el-table__header-wrapper) .operation-column .el-table__cell {
		color: transparent;
		transition: color 0.3s ease;
	}

	&:hover :deep(.el-table__header-wrapper) .operation-column .el-table__cell {
		color: var(--el-text-color-primary);
	}

	// 操作按钮容器悬停显示效果
	.table-operation-area {
		:deep(.el-table__body-wrapper) {
			// 操作按钮容器默认隐藏
			.operation-container {
				opacity: 1;
				visibility: visible;
				transform: none;
				pointer-events: auto;
				transition: none;
				display: flex;
				align-items: center;
				justify-content: center;
				flex-wrap: nowrap;
				overflow: visible;
				white-space: nowrap;
				gap: 0; // 完全去除容器间距

				// 专门针对WtmButton和所有按钮的样式覆盖 - 使用更高优先级
				.el-button,
				button,
				[class*='button'],
				[class*='el-button'],
				[class*='wtm-'],
				* {
					&[class*='button'],
					&[class*='el-button'],
					&[class*='wtm-'] {
						padding: 0 1px !important;
						margin: 0 -1px !important; // 使用负边距让按钮重叠1像素
						font-size: 13px !important;
						line-height: 1.1 !important;
						min-height: 18px !important;
						height: 18px !important;
						min-width: auto !important;
						background: transparent !important;
						border: none !important;
						box-shadow: none !important;
						border-radius: 2px !important;
						display: inline-flex !important;
						align-items: center !important;
						justify-content: center !important;
						gap: 0 !important; // 内部图标和文字无间距

						&:hover {
							background: var(--el-color-primary-light-9) !important;
							color: var(--el-color-primary) !important;
						}

						// 图标大小控制
						i {
							font-size: 10px !important;
						}

						// 文字大小控制
						span {
							font-size: 13px !important;
						}
					}
				}
			}

			// 悬停行时显示操作按钮
			tr:hover .operation-container {
				opacity: 1 !important;
				visibility: visible !important;
				transform: translateY(0) !important;
				pointer-events: auto !important;
			}

			// 悬停行背景变化
			tr:hover {
				background-color: var(--el-fill-color-light) !important;
			}
		}
	}
}

// 图片列表样式 - 与image类型保持一致
.table-image-container {
	.image-list-wrapper {
		display: flex;
		align-items: center;
		gap: 4px;
		flex-wrap: nowrap;
		overflow: hidden;
	}

	.more-images-indicator {
		display: flex;
		align-items: center;
		justify-content: center;
		background: rgba(0, 0, 0, 0.6);
		border: none;
		border-radius: 6px;
		cursor: pointer;
		transition: all 0.3s ease;
		backdrop-filter: blur(4px);
		min-width: 36px;
		margin-left: 2px;

		span {
			font-size: 11px;
			color: #ffffff;
			font-weight: 600;
			text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
		}

		&:hover {
			background: rgba(0, 0, 0, 0.8);
			transform: translateY(-1px);
			box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);

			span {
				color: #ffffff;
			}
		}

		&:active {
			transform: translateY(0);
			box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
		}
	}
}

// 文件预览样式
.table-file-preview-container {
	display: flex;
	justify-content: center;
	align-items: center;
	padding: 4px;

	.file-preview-wrapper {
		display: flex;
		align-items: center;
		gap: 4px;
		flex-wrap: nowrap;
		overflow: hidden;
	}

	.table-file-preview {
		border-radius: 8px;
		border: 2px solid #e4e7ed;
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
		transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
		cursor: pointer;
		overflow: hidden;
		display: flex;
		align-items: center;
		justify-content: center;
		position: relative;

		// 添加预览提示
		&::after {
			content: '点击查看';
			position: absolute;
			bottom: 0;
			left: 0;
			right: 0;
			background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
			color: white;
			font-size: 11px;
			text-align: center;
			padding: 4px;
			opacity: 0;
			transition: opacity 0.3s ease;
			pointer-events: none;
		}

		&:hover {
			border-color: #409eff;
			box-shadow: 0 6px 20px rgba(64, 158, 255, 0.25);
			transform: scale(1.08) translateY(-2px);

			&::after {
				opacity: 1;
			}

			:deep(.el-image__inner) {
				filter: brightness(1.1) contrast(1.05);
			}

			// 文件预览图片加载状态优化
			:deep(.el-image__placeholder) {
				background: linear-gradient(90deg, #f0f2f5 25%, #e6f4ff 50%, #f0f2f5 75%);
				background-size: 200% 100%;
				animation: shimmer 1.5s infinite;
				display: flex;
				align-items: center;
				justify-content: center;
				color: #999;
				font-size: 12px;
			}

			:deep(.el-image__error) {
				background: #fafafa;
				border: 1px dashed #d9d9d9;
				display: flex;
				align-items: center;
				justify-content: center;
				color: #999;
				font-size: 12px;
			}
		}

		&.table-file-preview-pdf {
			background: linear-gradient(135deg, #fff5f5 0%, #fef0f0 100%);

			.pdf-preview-icon {
				display: flex;
				flex-direction: column;
				align-items: center;
				justify-content: center;
				padding: 8px;

				i {
					font-size: 24px;
					color: #f56c6c;
					margin-bottom: 4px;
				}

				span {
					font-size: 10px;
					color: #f56c6c;
					font-weight: 500;
				}
			}
		}

		&.table-file-preview-other {
			background: linear-gradient(135deg, #f4f4f5 0%, #f0f0f0 100%);

			.other-file-icon {
				display: flex;
				flex-direction: column;
				align-items: center;
				justify-content: center;
				padding: 8px;

				i {
					font-size: 24px;
					color: #909399;
					margin-bottom: 4px;
				}

				span {
					font-size: 10px;
					color: #909399;
					font-weight: 500;
				}
			}
		}
	}

	.more-files-indicator {
		display: flex;
		align-items: center;
		justify-content: center;
		background: rgba(0, 0, 0, 0.6);
		border: none;
		border-radius: 6px;
		cursor: pointer;
		transition: all 0.3s ease;
		backdrop-filter: blur(4px);
		min-width: 36px;
		margin-left: 2px;

		span {
			font-size: 11px;
			color: #ffffff;
			font-weight: 600;
			text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
		}

		&:hover {
			background: rgba(0, 0, 0, 0.8);
			transform: translateY(-1px);
			box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
		}
	}
}

/* 旧的预览样式已移除，现在使用独立的FilePreview组件 */

// 加载动画
@keyframes rotate {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(360deg);
	}
}

// 图片加载shimmer动画
@keyframes shimmer {
	0% {
		background-position: -200% 0;
	}
	100% {
		background-position: 200% 0;
	}
}

// 拖拽样式 - 无装饰版
.tool-sortable-item {
	cursor: move;
	padding: 4px 8px;
	margin: 0;

	&.dragging {
		opacity: 0.4;
	}

	.handle {
		margin-right: 4px;
		color: var(--el-text-color-placeholder);
		font-size: 11px;
	}
}

/* 可编辑单元格样式 */
.editable-cell-wrapper {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 8px;
	border-radius: 4px;
	cursor: pointer;
	transition: all 0.2s ease;
	border: 1px dashed #e0e8f0;
	width: 100%;
	position: relative;
	background-color: #fafcff;

	.editable-cell {
		flex: 1;
		min-width: 0;
	}

	.editable-icon {
		font-size: 12px;
		color: var(--el-color-primary);
		opacity: 0.5;
		transition: all 0.2s ease;
		flex-shrink: 0;
	}

	&:hover {
		background-color: var(--el-color-primary-light-9);
		border-color: var(--el-color-primary);
		border-style: solid;

		.editable-icon {
			opacity: 1;
			transform: scale(1.1);
		}
	}
}

/* 编辑状态下的行样式 */
:deep(.el-table .el-table__row.editing-row) {
	background-color: #f0f9ff;
	box-shadow: inset 3px 0 0 var(--el-color-primary);

	td {
		background-color: #f0f9ff !important;
	}
}

:deep(.el-table .el-table__row.editing-row:hover) {
	background-color: #e0f2fe !important;

	td {
		background-color: #e0f2fe !important;
	}
}

/* 批量编辑工具栏 */
.batch-edit-toolbar {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 8px 12px;
	margin-bottom: 10px;
	background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
	border: 1px solid #bae6fd;
	border-left: 3px solid var(--el-color-primary);
	border-radius: 4px;
	animation: slideInDown 0.3s ease-out;

	.batch-edit-info {
		display: flex;
		align-items: center;
		gap: 6px;
		color: #0369a1;
		font-size: 13px;

		i {
			font-size: 14px;
			color: var(--el-color-primary);
		}

		strong {
			color: var(--el-color-primary);
			font-size: 14px;
			font-weight: 600;
			margin: 0 2px;
		}
	}

	.batch-edit-actions {
		display: flex;
		gap: 8px;
	}
}

@keyframes slideInDown {
	from {
		opacity: 0;
		transform: translateY(-10px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* 批量保存按钮 */
.batch-save-btn {
	font-weight: 500;
	padding: 6px 16px !important;
	font-size: 13px;
	border-radius: 4px;
	transition: all 0.2s ease;

	i {
		font-size: 13px;
		margin-right: 4px;
	}

	&:hover {
		transform: translateY(-1px);
		box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
	}

	&:active {
		transform: translateY(0);
	}
}

/* 取消全部按钮 */
.batch-cancel-btn {
	font-weight: 500;
	padding: 6px 14px !important;
	font-size: 13px;
	border-radius: 4px;
	background-color: #ffffff;
	border: 1px solid #d1d5db;
	color: #6b7280;
	transition: all 0.2s ease;

	i {
		font-size: 13px;
		margin-right: 4px;
	}

	&:hover {
		background-color: #f9fafb;
		border-color: #9ca3af;
		color: #374151;
		box-shadow: 0 1px 4px rgba(107, 114, 128, 0.15);
	}

	&:active {
		background-color: #f3f4f6;
	}
}
</style>
